Skip to content

v2.4.0

Latest

Choose a tag to compare

@github-actions github-actions released this 05 Nov 17:37
v2.4.0
a8386f8

What's Changed

  • ci(release): pin Linux builds and cap the notes by Bjarne Oeverli (@bjarneo) (a8386f8)
  • docs(site): include WebM among the FFmpeg formats by Charlyls (@cartudev) (05dd52e)
  • docs(site): list MP4 among the local audio formats by Charlyls (@cartudev) (3bb9cc1)
  • style: gofmt the mp4 audio extension test by Charlyls (@cartudev) (2cc9734)
  • feat(player): accept the audio stream of .mp4 files by Charlyls (@cartudev) (0fc1e7a)
  • fix(ui): follow terminal colors in Ethereal by Bjarne Oeverli (@bjarneo) (9928143)
  • feat(navidrome): add track ratings by manuaudio (@manuaudio) (e30c677)
  • feat(netease): add a cookies_file option by JazibAli360 (@JazibAli360) (8b1fe18)
  • fix(resolve): play on.soundcloud.com short links by Renan Bezerra Guimarães (@RenanBezerraGuima) (5e36da0)
  • test(lyrics): make the repeated timestamps test table-driven, add fraction and BOM cases by Jay Hemnani (@jayhemnani9910) (d708f65)
  • docs(playlists): say relative paths in a local PLS file resolve from its folder by Jay Hemnani (@jayhemnani9910) (0424e29)
  • fix(nix): refresh the vendor hash after the Telegram provider by Charlyls (@cartudev) (6f5a67e)
  • fix(nix): refresh the vendor hash for the Go 1.27 toolchain by Charlyls (@cartudev) (1288b78)
  • fix(nix): build with the Go 1.27 toolchain by Charlyls (@cartudev) (2385d92)
  • docs(mediactl): correct the --player=cliamp note by Bjarne Oeverli (@bjarneo) (ac76422)
  • fix(ui): sanitize remote text before rendering (#685) by Acts1631 (@acts-1631) (f1296c9)
  • feat(telegram): add a native MTProto Telegram provider (#651) by Carlos (@cartudev) (a65244f)
  • feat(remote): add --params-file and --params-stdin to cliamp remote call (#641) by Renan Bezerra Guimarães (@RenanBezerraGuima) (fda4d4b)
  • docs(plugins): list album_art_url in the event payloads (#654) by Carlos (@cartudev) (87d929e)
  • feat(playlist): reverse the playlist order with Ctrl+O (#667) by Knut Åbjørsbråten (@Knutsi) (6a6fb24)
  • fix(ui): align numbers in playlist search results (#674) by IgorM (@maliavko) (93c54bc)
  • fix(plex): read the album year of a track (#676) by IgorM (@maliavko) (34e4cad)
  • fix(tomlutil): match spaced and quoted headers by Ehab Kahwati (@Devehab) (c329220)
  • fix(tomlutil): skip escaped quotes in """ strings by Ehab Kahwati (@Devehab) (1d22a1c)
  • fix(tomlutil): tighten header detection by Ehab Kahwati (@Devehab) (3c72a8b)
  • fix(tomlutil): handle header comments and [table] headers by Ehab Kahwati (@Devehab) (aed5bb9)
  • fix(lyrics): show LRC lines at every time tag, in time order by Jay Hemnani (@jayhemnani9910) (f490f07)
  • fix(radio): warn about unknown sections in radios.toml by Ehab Kahwati (@Devehab) (0baf1cd)
  • fix(spotify): give album tracks the album's cover by BAK (@BAKocska) (84096f8)
  • fix(resolve): resolve PLS paths against its folder by Jay Hemnani (@jayhemnani9910) (cb09863)
  • fix(kittyimg): size the image before decoding it (#653) by Carlos (@cartudev) (02309c9)
  • test(luaplugin): drop an unused layout fake field by Bjarne Oeverli (@bjarneo) (d693e82)
  • feat(ipc): add a start index to provider.load (#626) by Chad Thackray (@ChadThackray) (2a5e97b)
  • fix(luaplugin): stop logging a Lua error as a timeout (#625) by Chad Thackray (@ChadThackray) (ebe3301)
  • fix(player): trim MP3 encoder delay and padding (#623) by rxvt (@rxvt) (a33f600)
  • fix: bump Go to 1.26.10 for govulncheck by Bjarne Oeverli (@bjarneo) (9d61173)
  • feat(bandcamp): stream your purchased collection (#521) by Lukasz Jagiello (@ljagiello) (195d8ae)
  • refactor: add more constraints to lyrics and artist lookup by bl4zee (@bl4zee1g) (620e9fe)
  • docs(plugins): document the image, layout, ui and vis APIs by Charlyls (@cartudev) (1b71802)
  • fix(plugins): open image paths without blocking on a FIFO by Charlyls (@cartudev) (28746d9)
  • fix(plugins): close the remaining review findings by Charlyls (@cartudev) (270ebd6)
  • fix(plugins): address the review by Charlyls (@cartudev) (0136634)
  • feat(plugins): render image panes as text blocks by Charlyls (@cartudev) (1f88895)
  • feat(plugins): let plugins build panes, images and selectors by Charlyls (@cartudev) (3aad360)
  • fix(plugins): validate and normalize allowed private address ports by Lukasz Chojnacki (@lchojnack) (e2a1b8c)
  • feat(plugins): allow exact private addresses for self-hosted servers by Lukasz Chojnacki (@lchojnack) (f11b49e)
  • fix: soundcloud: properly report artist by bl4zee (@bl4zee1g) (c087629)
  • test(resolve): build a valid file URI for Windows paths by Jay Hemnani (@jayhemnani9910) (45b2f38)
  • fix(resolve): accept the largest EXTINF duration by Jay Hemnani (@jayhemnani9910) (96d3be9)
  • fix(resolve): play file:// entries in playlists by Jay Hemnani (@jayhemnani9910) (f0bd99d)
  • fix(resolve): read EXTINF titles after attributes by Jay Hemnani (@jayhemnani9910) (83ade3e)
  • feat(ui): add the Ethereal visualizer by Bjarne Oeverli (@bjarneo) (5656a55)
  • fix(review): hide EQ shortcut in minimal layout by SomSamantray (@SomSamantray) (9247dcc)
  • docs(eq): document previous preset shortcut by SomSamantray (@SomSamantray) (1cd10a0)
  • feat(eq): add previous preset shortcut by SomSamantray (@SomSamantray) (8651319)
  • docs: name Windows source build toolchain by SomSamantray (@SomSamantray) (8f4f98f)
  • docs: clarify Windows source build requirements by SomSamantray (@SomSamantray) (8408f49)
  • fix: bump Go and x/net for govulncheck by Bjarne Oeverli (@bjarneo) (ce8c65f)
  • fix: skip a dead YouTube track and honor track limits by Bjarne Oeverli (@bjarneo) (091a143)
  • fix(ui): open local files off the UI thread by Bjarne Oeverli (@bjarneo) (645346c)
  • docs: match Windows config directory by Bjarne Oeverli (@bjarneo) (c04406c)
  • fix:respect hidden help bar in full screen visualizer by Raushan Kumar (@raushankumar72) (5d47a75)
  • docs(site): describe hidden-file scans by Bjarne Oeverli (@bjarneo) (48c56a3)
  • feat(provider): find songs related to a Spotify or YouTube track (#581) by Gjermund Garaba (@gjermundgaraba) (0e3afcf)
  • docs(site): note GNOME Keyring cookie dependency by jacobius (@jakovius) (6237b70)
  • docs(ytmusic): include Debian and Ubuntu secretstorage package by jacobius (@jakovius) (bd1face)
  • fix(setup): retain Chromium cookie-source example by jacobius (@jakovius) (6f16c6e)
  • fix(resolve): skip dotfiles when scanning folders by Daniel Bae (@MrBeldum) (7c05974)
  • fix(ui): report favorite toggles in the status line by Taha Sadough (@tahadx) (080d0a8)
  • fix(ui): stop status messages from shifting the frame by Taha Sadough (@tahadx) (d11bce4)
  • feat(radio): show live listener counts on cliamp radio rows by Taha Sadough (@tahadx) (646b573)
  • chore: exclude website, docs and generated files from language stats by Taha Sadough (@tahadx) (f4f0882)
  • fix(ui): Space advances only when marking tracks by Taha Sadough (@tahadx) (0760dbd)
  • fix(ui): use a check for marked tracks instead of a star by Taha Sadough (@tahadx) (f2a3318)
  • fix(ui): q closes the info, lyrics and device overlays by Taha Sadough (@tahadx) (ea4e6f1)
  • fix(ui): q closes the playlist manager and queue overlays by Taha Sadough (@tahadx) (56e7ed8)
  • docs: require a description body on every commit by Taha Sadough (@tahadx) (2638110)
  • fix(ui): name key targets in help and drop dead n hints by Taha Sadough (@tahadx) (ed39a3c)
  • fix(ui): keep overlays open when switching to an unconfigured provider by Taha Sadough (@tahadx) (5675ddd)
  • fix(ui): reject non-terminal stdout by Neo Lehmann (@legacynode) (2084402)
  • fix(ui): hint valid keys on stray presses in confirm prompts by Taha Sadough (@tahadx) (d2c4d6e)
  • fix(ui): confirm before clearing the queue by Taha Sadough (@tahadx) (792ad4e)
  • fix(ui): advertise q as a close key for overlays by Taha Sadough (@tahadx) (cdd2679)
  • fix(ui): q exits the full-screen visualizer instead of quitting by Taha Sadough (@tahadx) (dc4d489)
  • fix(ui): open playlist manager with p from any provider pane by Taha Sadough (@tahadx) (0714c18)
  • feat(ui): show hidden shortcuts, hint unconfigured providers, clarify errors by Taha Sadough (@tahadx) (575610f)
  • fix(ui): let Esc leave the provider browser with an empty playlist by david s (@davidszp) (59d0ce4)
  • fix(spotify): rebuild the session when the access point closes by BAK (@BAKocska) (355fc30)
  • feat(ui): add YinYang visualizer mode by Erik Johansson (@erikrjohansson) (3e61ebe)
  • fix(radio): jump to cliamp radio immediately with loading indicator by Taha Sadough (@tahadx) (d35e4e9)
  • remove extra playlist page for simplicity. the new playlist page is the playlist manager by Taha Sadough (@tahadx) (e36a777)
  • test: make the new tests pass on Windows by Bjarne Oeverli (@bjarneo) (b1a8848)
  • build(nix): update the Go vendor hash by Bjarne Oeverli (@bjarneo) (d776878)
  • docs: add mac-notify to community plugins by David E. Barrera (@dbarrerap) (026c1b5)
  • fix(playlist): read the LIST INFO tags of WAV files by Bjarne Oeverli (@bjarneo) (0f42e20)
  • fix(view): wrap the too-small message to the terminal width by Bjarne Oeverli (@bjarneo) (387b147)
  • fix(model): give Lua track events the decoded duration by Bjarne Oeverli (@bjarneo) (2d1ce69)
  • fix(cli): keep zero position, volume and index in status --json by Bjarne Oeverli (@bjarneo) (8150661)
  • fix(ipc): name a socket path that is too long by Bjarne Oeverli (@bjarneo) (b38d1be)
  • fix(ipc): reject unknown shuffle, repeat and mono values by Bjarne Oeverli (@bjarneo) (c930bfc)
  • fix(cli): send an absolute path from cliamp queue by Bjarne Oeverli (@bjarneo) (96a095b)
  • fix(lyrics): treat a NetEase reply with no song list as not found by Bjarne Oeverli (@bjarneo) (9321e91)
  • docs(claude): state that tests read the docs and the example config by Bjarne Oeverli (@bjarneo) (4de3ae7)
  • docs(claude): isolate HOME only for the cliamp binary by Bjarne Oeverli (@bjarneo) (b5c552e)
  • docs(claude): list the platform file suffixes that the tree uses by Bjarne Oeverli (@bjarneo) (81b8cbf)
  • docs(keys): name SoundCloud and Yandex Music as Ctrl+F providers by Bjarne Oeverli (@bjarneo) (12b7e2a)
  • docs(headless): link the Hotkeys section by its real anchor by Bjarne Oeverli (@bjarneo) (531bd1f)
  • docs(headless): state that theme list and vis list still work by Bjarne Oeverli (@bjarneo) (c6cee64)
  • docs(config): list every EQ preset, visualizer and provider by Bjarne Oeverli (@bjarneo) (2b174df)
  • fix(cli): show true as the --expand-playlist default in help by Bjarne Oeverli (@bjarneo) (8064f63)
  • fix(cli): accept --version without a version from ldflags by Bjarne Oeverli (@bjarneo) (65bd67b)
  • docs(cli): state that the sample rate default is 0 for auto by Bjarne Oeverli (@bjarneo) (3c18938)
  • build: format untracked Go files and skip deleted ones by Bjarne Oeverli (@bjarneo) (3454024)
  • ci: run the test suite once and list the skips from its log by Bjarne Oeverli (@bjarneo) (f28548f)
  • docs(headless): name the servers that get playback reports by Bjarne Oeverli (@bjarneo) (831d2c9)
  • docs(plugins): state that cliamp.player.seek seeks relative by Bjarne Oeverli (@bjarneo) (f07020e)
  • docs(plugins): name only free keys in the p:bind examples by Bjarne Oeverli (@bjarneo) (a33d018)
  • refactor(favorites): delete the unused Favorite, Remove and Clear by Bjarne Oeverli (@bjarneo) (072918a)
  • fix(history): take realtime and restricted from a provider replay by Bjarne Oeverli (@bjarneo) (27c3095)
  • docs(cli): state that history --limit only limits the output by Bjarne Oeverli (@bjarneo) (4e09cba)
  • fix(resolve): take an existing path literally before a glob by Bjarne Oeverli (@bjarneo) (3cfe93e)
  • test(netdiag): build the wrapped dial error the way Streaming does by Bjarne Oeverli (@bjarneo) (bd95097)
  • fix(local): leave the hidden Favorites.toml out of search results by Bjarne Oeverli (@bjarneo) (2a77cd8)
  • fix(radio): lock and reload the pins file for each toggle by Bjarne Oeverli (@bjarneo) (6b76878)
  • docs(httpclient): state where stream and API proxy rules differ by Bjarne Oeverli (@bjarneo) (3f8c925)
  • fix(plex): stop paging when the server ignores the start offset by Bjarne Oeverli (@bjarneo) (eb608d1)
  • fix(local): read no directory tags while the playlist lock is held by Bjarne Oeverli (@bjarneo) (877fa4f)
  • fix(local): keep duplicate tracks when a playlist is saved by Bjarne Oeverli (@bjarneo) (5450f73)
  • fix(upgrade): restart the idle timer when the headers arrive by Bjarne Oeverli (@bjarneo) (ef2b31e)
  • fix(upgrade): read the release list up to 16 MiB by Bjarne Oeverli (@bjarneo) (e4072cf)
  • fix(upgrade): never downgrade with --prerelease by Bjarne Oeverli (@bjarneo) (8852129)
  • docs(providers): drop stale stream.go and webAPIOnce lock comments by Bjarne Oeverli (@bjarneo) (6b34c36)
  • fix(spotify): ask for sign-in when the Web API rejects the token by Bjarne Oeverli (@bjarneo) (effb5d2)
  • fix(qobuz,tidal): keep a newer client when an old request fails auth by Bjarne Oeverli (@bjarneo) (b21eba3)
  • refactor(netease): take the yt-dlp install hint from internal/ytdlp by Bjarne Oeverli (@bjarneo) (aa683c7)
  • fix(ytmusic): keep a browser sign-in when a silent check runs by Bjarne Oeverli (@bjarneo) (1c3bcd1)
  • docs(config): match the setup and bool docs to the code by Bjarne Oeverli (@bjarneo) (e0c39ec)
  • fix(config): ignore NaN and infinite numbers in config.toml by Bjarne Oeverli (@bjarneo) (3937be2)
  • fix(config): keep quoted commas and read a # right after a close by Bjarne Oeverli (@bjarneo) (0cebfa6)
  • fix(config): lock config.toml for each read, edit and write by Bjarne Oeverli (@bjarneo) (7e70ce4)
  • fix(config): add a new top-level key after the last top-level key by Bjarne Oeverli (@bjarneo) (763e0aa)
  • fix(config): save every line of a duplicate top-level key by Bjarne Oeverli (@bjarneo) (2354eda)
  • fix(playlist): stop enrich of a virtual playlist before the probes by Bjarne Oeverli (@bjarneo) (f2945b2)
  • test(playlist): cover the enrich probe and merge rules by Bjarne Oeverli (@bjarneo) (7fd5553)
  • fix(playlist): let doctor --fix skip the virtual Favorites playlist by Bjarne Oeverli (@bjarneo) (e13e104)
  • fix(config): read the plugin keys that cliamp uses with the value rules by Bjarne Oeverli (@bjarneo) (0f97463)
  • fix(setup): check a $NAME url through its variable by Bjarne Oeverli (@bjarneo) (2007d8c)
  • fix(setup): save the NetEase user_id that the probe finds by Bjarne Oeverli (@bjarneo) (a4abfb3)
  • fix(luaplugin): load plugins only with the approved permissions by Bjarne Oeverli (@bjarneo) (15b2742)
  • fix(luaplugin): refuse a second plugin.register call by Bjarne Oeverli (@bjarneo) (1b47a5c)
  • fix(pluginmgr): approve only the plugin content that trust showed by Bjarne Oeverli (@bjarneo) (b4b0b5b)
  • fix(luaplugin): stop plugin commands at the start of Close by Bjarne Oeverli (@bjarneo) (bd5d114)
  • fix(luaplugin): stop exec child processes that hold the output pipes by Bjarne Oeverli (@bjarneo) (17d8460)
  • fix(luaplugin): end blocking plugin APIs with the call time limit by Bjarne Oeverli (@bjarneo) (2425852)
  • fix(luaplugin): run coroutines under the call that resumes them by Bjarne Oeverli (@bjarneo) (c2d6fe0)
  • fix(pluginmgr): drop control characters from the plugin list by Bjarne Oeverli (@bjarneo) (56a47f8)
  • fix(luaplugin): send plugin print output to plugins.log by Bjarne Oeverli (@bjarneo) (8df8303)
  • fix(luaplugin): read visualizer objects under the plugin lock by Bjarne Oeverli (@bjarneo) (fc625da)
  • fix(luaplugin): reject store values that JSON cannot hold by Bjarne Oeverli (@bjarneo) (928710c)
  • fix(luaplugin): skip player controls until the provider is set by Bjarne Oeverli (@bjarneo) (b274e7b)
  • fix(luaplugin): keep plugins from writing the IPC PID file by Bjarne Oeverli (@bjarneo) (9ead3c6)
  • fix(luaplugin): report the repeat mode in the case the provider uses by Bjarne Oeverli (@bjarneo) (9696dec)
  • fix(mediactl): keep the MPRIS track id when only the length changes by Bjarne Oeverli (@bjarneo) (e6535b7)
  • fix(mediactl): stop an MPRIS update panic after the bus drops by Bjarne Oeverli (@bjarneo) (23c66b7)
  • fix(player): mark an ICY file finite before the prefetch reads it by Bjarne Oeverli (@bjarneo) (d7f1257)
  • fix(player): decode yt-dlp audio off the speaker callback by Bjarne Oeverli (@bjarneo) (70e5f79)
  • fix(player): end a cleanly finished prefetch stream with a short read by Bjarne Oeverli (@bjarneo) (bcb4629)
  • fix(player): let Stop and a skip interrupt a stalled yt-dlp read by Bjarne Oeverli (@bjarneo) (245e72e)
  • fix(player): skip the yt-dlp seek mute after a track change by Bjarne Oeverli (@bjarneo) (98c18df)
  • fix(player): close the dropped preload off the prepared seek path by Bjarne Oeverli (@bjarneo) (c4973c0)
  • docs(player): fix the ClearPreload and PlayAt comments by Bjarne Oeverli (@bjarneo) (d2cc938)
  • fix(theme): skip a user theme named default by Bjarne Oeverli (@bjarneo) (272c394)
  • fix(theme): skip theme files that lack any of the six colors by Bjarne Oeverli (@bjarneo) (4a993cf)
  • test(ui): pin 1-row and wide visualizer frames in the golden hashes by Bjarne Oeverli (@bjarneo) (ced8102)
  • fix(ui): keep Lua visualizer names on each Visualizer by Bjarne Oeverli (@bjarneo) (0741ae1)
  • fix(model): init a Lua visualizer with the real terminal size by Bjarne Oeverli (@bjarneo) (b726534)
  • refactor(model): keep the frame padding on the Model by Bjarne Oeverli (@bjarneo) (a475f92)
  • docs(cli): list Stereo with the modes that already tick at 60 FPS by Bjarne Oeverli (@bjarneo) (ba4f02b)
  • refactor(ui): drop the unused Visualizer.SampleBuf by Bjarne Oeverli (@bjarneo) (fbb1ee0)
  • style(model): tidy the undo comment and a queue edit test by Bjarne Oeverli (@bjarneo) (b6c14e9)
  • fix(model): refresh Recently Played views after IPC history.clear by Bjarne Oeverli (@bjarneo) (b1d4ab6)
  • docs(headless): start the scripted queue with cliamp play by Bjarne Oeverli (@bjarneo) (3964f65)
  • fix(model): re-arm the preload through one guarded helper by Bjarne Oeverli (@bjarneo) (56ca97b)
  • fix: wait for queued playback reports at exit by Bjarne Oeverli (@bjarneo) (2b4eea6)
  • fix(model): scrobble the track that plays at quit by Bjarne Oeverli (@bjarneo) (748f358)
  • fix(model): drop a pending seek on stop by Bjarne Oeverli (@bjarneo) (4846637)
  • fix(model): skip Recently Played as the loaded list of the manager by Bjarne Oeverli (@bjarneo) (caaf921)
  • fix: keep the order of V2 jobs sent back to back by Bjarne Oeverli (@bjarneo) (6e02e58)
  • fix(model): publish runtime state when a buffering stream starts by Bjarne Oeverli (@bjarneo) (1f55680)
  • fix(model): refuse a queue move when its save fails by Bjarne Oeverli (@bjarneo) (10457a2)
  • fix(model): keep a detached track playing on a row removal by Bjarne Oeverli (@bjarneo) (943688e)
  • fix(model): go back a track on previous during a rewind by Bjarne Oeverli (@bjarneo) (841bd95)
  • fix(model): reset the playlist cursor on IPC queue.clear by Bjarne Oeverli (@bjarneo) (d52238d)
  • fix(model): end the radio batch on every queue replace by Bjarne Oeverli (@bjarneo) (a9db72b)
  • fix(model): follow an IPC rename of the loaded playlist by Bjarne Oeverli (@bjarneo) (ccde93b)
  • fix(model): undo a saved removal with one locked insert by Bjarne Oeverli (@bjarneo) (072181f)
  • fix(local): keep a track saved between two tracks in place by Bjarne Oeverli (@bjarneo) (306c8b9)
  • fix(model): refuse Ctrl+Z after a later queue edit by Bjarne Oeverli (@bjarneo) (f70f85b)
  • refactor(model): drop isOverlayActive from the tick decisions by Bjarne Oeverli (@bjarneo) (2abe115)
  • docs(model): describe what Update adds around update by Bjarne Oeverli (@bjarneo) (7b5982a)
  • fix(model): let the top overlay decide the content-first layout by Bjarne Oeverli (@bjarneo) (b3e34dc)
  • fix(model): block undo and the keymap on a too-small screen by Bjarne Oeverli (@bjarneo) (1774461)
  • fix(model): send input to the provider filter only with its focus by Bjarne Oeverli (@bjarneo) (91b9b2c)
  • fix(model): let the browser replace prompt own the keys by Bjarne Oeverli (@bjarneo) (79dd60c)
  • refactor(model): drop the plugin forwards of F and ctrl+r by Bjarne Oeverli (@bjarneo) (acac52c)
  • fix(luaplugin): refuse reserved keys in the top-level chunk of a plugin by Bjarne Oeverli (@bjarneo) (82fa231)
  • fix(model): drop a feed or file browser replace that lands late by Bjarne Oeverli (@bjarneo) (f39bae5)
  • fix(model): unpause a yt-dlp reconnect only on the same track by Bjarne Oeverli (@bjarneo) (0966fae)
  • test(main): cover the job events of the V2 server by Bjarne Oeverli (@bjarneo) (81bf955)
  • fix(main): save the exit state on signals in the TUI and on SIGHUP by Bjarne Oeverli (@bjarneo) (0a1d3b4)
  • fix(main): stop a second daemon before it loads the plugins by Bjarne Oeverli (@bjarneo) (6d4b2e8)
  • test(main): keep the test socket path short on macOS by Bjarne Oeverli (@bjarneo) (27b9ac7)
  • fix(main): print the IPC start error with one ipc prefix by Bjarne Oeverli (@bjarneo) (1a25782)
  • test(main): cover the V2 dispatcher, plugin jobs and startIPC by Bjarne Oeverli (@bjarneo) (e663d6e)
  • refactor(main): name the V2 dispatcher for both modes by Bjarne Oeverli (@bjarneo) (a4c6b3a)
  • docs(provider): wire the creds command into buildApp by Bjarne Oeverli (@bjarneo) (7c825dc)
  • docs(agents): isolate HOME and XDG dirs when running a test binary by Bjarne Oeverli (@bjarneo) (5c7dd2b)
  • docs(agents): complete the IPC operation steps and ui/model table by Bjarne Oeverli (@bjarneo) (2252880)
  • docs(provider): keep every buffered matcher and name the cookie hook by Bjarne Oeverli (@bjarneo) (5f9a800)
  • docs: add remote control and headless mode to the README and site by Bjarne Oeverli (@bjarneo) (ede2cee)
  • docs(provider): list every place that a new provider touches by Bjarne Oeverli (@bjarneo) (a5b9503)
  • docs(agents): map the packages, runtime and IPC of the new code by Bjarne Oeverli (@bjarneo) (d8e9eb7)
  • build(nix): keep local media and secrets out of the package source by Bjarne Oeverli (@bjarneo) (cb889bf)
  • ci: list the skipped tests after make ci by Bjarne Oeverli (@bjarneo) (840f7ec)
  • style(config): re-wrap the save doc comment by Bjarne Oeverli (@bjarneo) (c1e5248)
  • docs(mediactl): describe clamped and NaN MPRIS volume writes by Bjarne Oeverli (@bjarneo) (17b52c2)
  • test(model): isolate the config dir in the quick switch test by Bjarne Oeverli (@bjarneo) (97c6e80)
  • fix(mediactl): survive a lost bus in the volume republish by Bjarne Oeverli (@bjarneo) (e906230)
  • refactor(cmd): draw the radio globe from its own palette by Bjarne Oeverli (@bjarneo) (61693dd)
  • fix(config): keep a saved key beside the top-level keys by Bjarne Oeverli (@bjarneo) (0d3d8bc)
  • docs(yandex): name registerPlayerHooks as the resolver owner by Bjarne Oeverli (@bjarneo) (87c170b)
  • fix: keep the newest provider sign-in cancelable by Bjarne Oeverli (@bjarneo) (5d02302)
  • docs(model): name buildProviders in the provider key comment by Bjarne Oeverli (@bjarneo) (e586070)
  • refactor(tracksave): delete Save and resolve.DownloadYTDL by Bjarne Oeverli (@bjarneo) (4f1955f)
  • fix(model): stop an IPC save download on job.cancel by Bjarne Oeverli (@bjarneo) (23dbfa6)
  • fix(model): return from overlays after every provider quick switch by Bjarne Oeverli (@bjarneo) (d997bb5)
  • fix(model): let the manager delete prompt own provider shortcuts by Bjarne Oeverli (@bjarneo) (8047ad8)
  • docs(luaplugin): name lua_wiring.go in the provider comments by Bjarne Oeverli (@bjarneo) (a024eba)
  • docs(plugins): bind an unreserved key in the p:bind example by Bjarne Oeverli (@bjarneo) (a19d0d2)
  • fix(pluginmgr): check the trust manifest before install and remove by Bjarne Oeverli (@bjarneo) (95d28a7)
  • refactor(player): mark resolved Qobuz and Tidal sources as buffered by Bjarne Oeverli (@bjarneo) (219266a)
  • fix(mediactl): republish Volume after a clamped client Set by Bjarne Oeverli (@bjarneo) (35d12c3)
  • fix(mediactl): reject a NaN MPRIS volume by Bjarne Oeverli (@bjarneo) (e0a8f97)
  • fix(player): ignore NaN volume, speed and EQ values by Bjarne Oeverli (@bjarneo) (bfb9db9)
  • build: run the test suite once in the ci target by Bjarne Oeverli (@bjarneo) (b9fbdd3)
  • test(luaplugin): guard the plugin event count on the site by Bjarne Oeverli (@bjarneo) (384588f)
  • test(theme): guard the built-in theme count on the site by Bjarne Oeverli (@bjarneo) (8816def)
  • test(model): guard the EQ preset count on the site by Bjarne Oeverli (@bjarneo) (488a219)
  • test(ui): guard the visualizer counts on the site by Bjarne Oeverli (@bjarneo) (6ed5b11)
  • test(model): start changeEngine at its offset through the shared fake by Bjarne Oeverli (@bjarneo) (d49d055)
  • fix(model): skip the resume seek when a late start is past the hint by Bjarne Oeverli (@bjarneo) (0b498a5)
  • test(model): cover the resume seek after a failed start seek by Bjarne Oeverli (@bjarneo) (a9ec29c)
  • fix(cmd): report restricted tracks in cliamp history --json by Bjarne Oeverli (@bjarneo) (9e705f2)
  • fix(model): keep the gated hint off a failed local ffmpeg start by Bjarne Oeverli (@bjarneo) (eafb759)
  • docs(model): say what cancels an IPC url.load resolve by Bjarne Oeverli (@bjarneo) (c7c2ce6)
  • fix(model): skip the resume seek when playback starts at the hint by Bjarne Oeverli (@bjarneo) (66cb80f)
  • fix(model): skip the exit resume of any live stream by Bjarne Oeverli (@bjarneo) (3a8f869)
  • refactor(resolve): take a plain browser string in the batch resolvers by Bjarne Oeverli (@bjarneo) (874d84e)
  • fix(model): stop an IPC url.load when its client disconnects by Bjarne Oeverli (@bjarneo) (d8fc413)
  • refactor(model): check the batch host with playlist.IsYouTubeMusicURL by Bjarne Oeverli (@bjarneo) (559db16)
  • refactor(playlist): mark restricted tracks with Track.Restricted by Bjarne Oeverli (@bjarneo) (129384e)
  • refactor: move the yt-dlp installer next to the install prompt by Bjarne Oeverli (@bjarneo) (6faa0a8)
  • fix(player): close the dropped preload async after a native seek by Bjarne Oeverli (@bjarneo) (b50ff61)
  • refactor(player): share Err, Len and Position by the pipe streamers by Bjarne Oeverli (@bjarneo) (c145325)
  • refactor(player): share one timed peek by the ffmpeg and yt-dlp waits by Bjarne Oeverli (@bjarneo) (0da9b91)
  • fix(player): write ctrl under the speaker lock on the first start by Bjarne Oeverli (@bjarneo) (5747a3a)
  • refactor(player): share one position and duration rule by Bjarne Oeverli (@bjarneo) (4b71036)
  • test(model): share one engine fake across the model tests by Bjarne Oeverli (@bjarneo) (0bb36eb)
  • fix(model): start local ffmpeg formats off the Update goroutine by Bjarne Oeverli (@bjarneo) (bbc3b4b)
  • refactor(player): route yt-dlp pages inside the player by Bjarne Oeverli (@bjarneo) (3e994c3)
  • refactor(player): add IsLiveStream to Engine by Bjarne Oeverli (@bjarneo) (c692147)
  • refactor(player): drop IsStreamSeek from Engine by Bjarne Oeverli (@bjarneo) (7afa814)
  • refactor(player): send httpclient.UserAgent on stream requests by Bjarne Oeverli (@bjarneo) (9483c3b)
  • refactor(radio): cap every body read with httpclient.ReadBody by Bjarne Oeverli (@bjarneo) (1cca26c)
  • refactor(model): check the batch host with playlist.NormalizeHost by Bjarne Oeverli (@bjarneo) (9de146e)
  • refactor(model): pick the save download with tracksave.NeedsDownload by Bjarne Oeverli (@bjarneo) (1a69825)
  • fix(model): fit vis picker scroll to the rows after the apply by Bjarne Oeverli (@bjarneo) (2ce36ba)
  • refactor(model): share one header-aware scroll fit by three lists by Bjarne Oeverli (@bjarneo) (467993e)
  • refactor(model): draw the list overlays from one shownRows view by Bjarne Oeverli (@bjarneo) (d50c408)
  • refactor(model): group the jump, URL, info and provider pane fields by Bjarne Oeverli (@bjarneo) (9c976b1)
  • refactor(model): rename spotSearch to searchOverlay by Bjarne Oeverli (@bjarneo) (77df780)
  • refactor(model): lay out the frame in Update, not in View by Bjarne Oeverli (@bjarneo) (9453e4f)
  • refactor(ui): drop the PanelWidth and FrameStyle globals by Bjarne Oeverli (@bjarneo) (0498631)
  • refactor(model): read the panel width from the layout, not a global by Bjarne Oeverli (@bjarneo) (3b56463)
  • refactor(model): split the tick body into one method per job by Bjarne Oeverli (@bjarneo) (f5fbf89)
  • fix(model): share one next-track rule by skip, drain and gapless by Bjarne Oeverli (@bjarneo) (c039f5b)
  • refactor(model): move list cursor keys into stepListCursor by Bjarne Oeverli (@bjarneo) (3eb469c)
  • refactor(model): share one filterList by four list overlays by Bjarne Oeverli (@bjarneo) (b23e01f)
  • refactor(model): call effectivePlaylistVisible without wrappers by Bjarne Oeverli (@bjarneo) (21ce321)
  • fix(ui): redraw ClassicLED at its declared 30 FPS by Bjarne Oeverli (@bjarneo) (e433955)
  • refactor(model): keep every derived style in styles.go by Bjarne Oeverli (@bjarneo) (870247b)
  • test(model): prove that ctrl+z runs the playlist undo by Bjarne Oeverli (@bjarneo) (5a2c808)
  • test(model): walk every main key path function in the drift test by Bjarne Oeverli (@bjarneo) (37bcdf4)
  • docs(keybindings): give N its own row in the provider browser by Bjarne Oeverli (@bjarneo) (043d16f)
  • test(model): check the ctrl+r plugin forward in the playlist view by Bjarne Oeverli (@bjarneo) (018f9e5)
  • test(model): count provider shortcuts in the overlay drift test by Bjarne Oeverli (@bjarneo) (781c69b)
  • docs(yt-dlp): name Ctrl+S as the key that saves a track by Bjarne Oeverli (@bjarneo) (7e1557a)
  • docs(keybindings): list the provider shortcuts each view takes by Bjarne Oeverli (@bjarneo) (ae8e163)
  • test(model): check overlay key handlers against the registry by Bjarne Oeverli (@bjarneo) (572844b)
  • test(model): walk the main key path with go/ast by Bjarne Oeverli (@bjarneo) (c2001e7)
  • refactor(model): split handleKey by the owner of the key by Bjarne Oeverli (@bjarneo) (dad4711)
  • refactor(model): share the ctrl+r provider refresh by Bjarne Oeverli (@bjarneo) (f9bddc5)
  • refactor(model): look up provider shortcuts in one place by Bjarne Oeverli (@bjarneo) (1973519)
  • fix(model): show provider hints on the minimal tier by Bjarne Oeverli (@bjarneo) (68c4138)
  • test(model): check that overlayStack holds each screen once by Bjarne Oeverli (@bjarneo) (2c5d89d)
  • docs(model): say why the overlay order still matters by Bjarne Oeverli (@bjarneo) (7cfe24d)
  • refactor(model): drop unreachable ctrl+c and ctrl+k clauses by Bjarne Oeverli (@bjarneo) (30483f0)
  • fix(model): show the YouTube search over the nav browser by Bjarne Oeverli (@bjarneo) (913286b)
  • refactor(model): resolve the command mode in one place by Bjarne Oeverli (@bjarneo) (c1d3e68)
  • refactor(model): derive the overlay order from one table by Bjarne Oeverli (@bjarneo) (fca4817)
  • refactor(model): drop stale comment in handleNavAlbumsLoaded by Bjarne Oeverli (@bjarneo) (68ff7f6)
  • refactor(model): move the V2 response body to ipc_runtime.go by Bjarne Oeverli (@bjarneo) (61428eb)
  • refactor(model): move queue load message bodies to update_load.go by Bjarne Oeverli (@bjarneo) (66e739a)
  • refactor(model): move search message bodies to update_search.go by Bjarne Oeverli (@bjarneo) (1352ae0)
  • refactor(model): move nav browser message bodies to update_nav.go by Bjarne Oeverli (@bjarneo) (f42862e)
  • refactor(model): move provider message bodies to update_provider.go by Bjarne Oeverli (@bjarneo) (3e2c5cf)
  • refactor(model): move playback message bodies to update_playback.go by Bjarne Oeverli (@bjarneo) (0cba6b4)
  • refactor(model): move the tick body to handleTick in tick.go by Bjarne Oeverli (@bjarneo) (9020289)
  • refactor(model): move queue overlay keys to keys_queue.go by Bjarne Oeverli (@bjarneo) (0049aa9)
  • refactor(model): move picker keys to keys_pickers.go by Bjarne Oeverli (@bjarneo) (37e5885)
  • refactor(model): move search keys to keys_search.go by Bjarne Oeverli (@bjarneo) (e895484)
  • refactor(model): move the playlist order writer to queue_ops.go by Bjarne Oeverli (@bjarneo) (e8bfd1d)
  • refactor(model): move playlist manager keys to keys_plmgr.go by Bjarne Oeverli (@bjarneo) (3f993d5)
  • fix(model): report the play before a rewind only when it lands by Bjarne Oeverli (@bjarneo) (ec353ff)
  • fix(model): drop a waiting progress report that a newer one replaces by Bjarne Oeverli (@bjarneo) (46391c5)
  • fix(model): start a rewind replay only when the rewind lands by Bjarne Oeverli (@bjarneo) (06b0bb0)
  • test(model): cover each stop path that scrobbles the left track by Bjarne Oeverli (@bjarneo) (8a9ffc8)
  • refactor(model): find a capable provider through one findCapable by Bjarne Oeverli (@bjarneo) (2d3ac97)
  • fix(lyrics): report an oversized lyrics response as too large by Bjarne Oeverli (@bjarneo) (c588cc1)
  • refactor(model): notify the media controls once per playback change by Bjarne Oeverli (@bjarneo) (c0ef619)
  • fix(model): scrobble a left track through one leaveTrack by Bjarne Oeverli (@bjarneo) (21b8c0a)
  • fix(model): send playback reports to providers in order by Bjarne Oeverli (@bjarneo) (ba061c6)
  • refactor(lyrics): look up lyrics in one order with lyrics.Lookup by Bjarne Oeverli (@bjarneo) (9b2f742)
  • refactor(model): split ICY stream titles with one rule by Bjarne Oeverli (@bjarneo) (4e9abae)
  • fix(model): refuse a dir track removal only for a mirrored playlist by Bjarne Oeverli (@bjarneo) (eda60fc)
  • fix(model): record a removal undo only for the x key by Bjarne Oeverli (@bjarneo) (14ae2e5)
  • docs(site): say that a Lua queue move under shuffle changes nothing by Bjarne Oeverli (@bjarneo) (3958541)
  • test(model): cover the immediate preload re-arm of each queue edit by Bjarne Oeverli (@bjarneo) (f3372ee)
  • fix(model): play a queue row through one playIndex verb by Bjarne Oeverli (@bjarneo) (a91425e)
  • fix(model): reload only the Local pane after a history or favorite write by Bjarne Oeverli (@bjarneo) (c863c41)
  • fix(model): apply one rule to key, IPC and Lua queue edits by Bjarne Oeverli (@bjarneo) (912f979)
  • refactor(model): append to the queue through appendTracks by Bjarne Oeverli (@bjarneo) (b48f615)
  • refactor(provider): add AddTracks for the batch writer fallback by Bjarne Oeverli (@bjarneo) (05cc7d1)
  • refactor(model): route playback messages and V2 through the verbs by Bjarne Oeverli (@bjarneo) (29f1faf)
  • refactor(model): route the keys through one verb per playback action by Bjarne Oeverli (@bjarneo) (e1be098)
  • refactor(model): save config through the typed savers by Bjarne Oeverli (@bjarneo) (25f9999)
  • fix(model): name a failed resume a track, not a show by Bjarne Oeverli (@bjarneo) (35d459f)
  • refactor(model): keep the playlist updater seam inside ui/model by Bjarne Oeverli (@bjarneo) (c7e9435)
  • refactor(model): drop the catalog fallback of the IPC provider search by Bjarne Oeverli (@bjarneo) (adf85de)
  • docs(model): say that only old files reload resolver tracks as files by Bjarne Oeverli (@bjarneo) (f59919a)
  • fix(model): resume a network stream seek off the Update goroutine by Bjarne Oeverli (@bjarneo) (0746384)
  • feat(cmd): add provider_meta to cliamp history --json by Bjarne Oeverli (@bjarneo) (6011b77)
  • fix(cmd): state the track-start rule in the empty history message by Bjarne Oeverli (@bjarneo) (2bf622c)
  • test(model): prove the IPC radio search keeps the pane search by Bjarne Oeverli (@bjarneo) (b7db676)
  • feat(radio): add SearchStations, a station search with no pane state by Bjarne Oeverli (@bjarneo) (07775f5)
  • fix(model): keep other writers' changes on a queue or manager edit by Bjarne Oeverli (@bjarneo) (9ff8c72)
  • fix(local): scan no directory while UpdatePlaylist holds the lock by Bjarne Oeverli (@bjarneo) (a2ba51f)
  • docs(model): name buildProviders as the owner of the shared stores by Bjarne Oeverli (@bjarneo) (d83bfff)
  • docs(model): name the picker lists of any searched provider by Bjarne Oeverli (@bjarneo) (3f8674b)
  • fix: keep provider URI tracks off the Update goroutine after a reload by Bjarne Oeverli (@bjarneo) (b9dbd22)
  • fix(model): keep the pane search on an IPC station search by Bjarne Oeverli (@bjarneo) (58aa263)
  • feat(playlist): keep the album art URL in favorites and history by Bjarne Oeverli (@bjarneo) (9c4d306)
  • refactor(playlist): delete the unused Playlist.ToggleBookmark by Bjarne Oeverli (@bjarneo) (a09c831)
  • fix(local): run playlist read-modify-write under the playlist lock by Bjarne Oeverli (@bjarneo) (0697686)
  • refactor(playlist): mark favorite rows in PlaylistInfo by Bjarne Oeverli (@bjarneo) (54178ad)
  • refactor(model): find synced lyrics by provider capability by Bjarne Oeverli (@bjarneo) (fa7b8c8)
  • refactor(local): move the Favorites.toml rename to startup by Bjarne Oeverli (@bjarneo) (f76628c)
  • refactor: build the favorites and history stores once by Bjarne Oeverli (@bjarneo) (6576ccb)
  • refactor(playlist): move the audio extension set out of player by Bjarne Oeverli (@bjarneo) (5f0e226)
  • refactor(model): unexport playsLive by Bjarne Oeverli (@bjarneo) (bef5d03)
  • fix(model): publish the plugin state before app.start by Bjarne Oeverli (@bjarneo) (2e6bb79)
  • fix(lua): queue every plugin control instead of dropping it by Bjarne Oeverli (@bjarneo) (a9590ab)
  • fix(ipc): mark only the active visualizer row in vis list by Bjarne Oeverli (@bjarneo) (d88b832)
  • perf(model): build the Lua queue rows on the first read by Bjarne Oeverli (@bjarneo) (01fc29b)
  • fix(model): publish the plugin state before each plugin event by Bjarne Oeverli (@bjarneo) (bcae21e)
  • docs(site): name the init and destroy of Lua visualizers by Bjarne Oeverli (@bjarneo) (df282d3)
  • fix(pluginmgr): list no plugin as trusted from a bad manifest by Bjarne Oeverli (@bjarneo) (a7fe911)
  • refactor(model): hand Lua a loader that holds only the state store by Bjarne Oeverli (@bjarneo) (3b0fa28)
  • docs(luaplugin): say how the Lua providers reach the Model by Bjarne Oeverli (@bjarneo) (250b426)
  • docs(plugins): state what os.getenv and cliamp.fs can read by Bjarne Oeverli (@bjarneo) (c06fbae)
  • refactor(luaplugin): build the plugin data write root with appdir by Bjarne Oeverli (@bjarneo) (7d457fa)
  • fix(pluginmgr): explain a trust manifest that does not parse by Bjarne Oeverli (@bjarneo) (868e807)
  • fix(ipc): list Lua visualizer modes in vis list by Bjarne Oeverli (@bjarneo) (fcc7553)
  • fix(ui): keep built-in visualizer names from Lua plugins by Bjarne Oeverli (@bjarneo) (340ec5b)
  • fix(ui): give Lua visualizers the smoothed spectrum bands by Bjarne Oeverli (@bjarneo) (1b513c6)
  • fix(ui): run the init and destroy of Lua visualizers by Bjarne Oeverli (@bjarneo) (82bdda4)
  • fix(luaplugin): let set_volume reach the volume_min floor by Bjarne Oeverli (@bjarneo) (7b90446)
  • perf(model): build each plugin event only when a hook wants it by Bjarne Oeverli (@bjarneo) (9e09c4b)
  • fix(lua): read plugin state from a snapshot that the Model publishes by Bjarne Oeverli (@bjarneo) (a838047)
  • refactor(luaplugin): read the Lua track through one CurrentTrack by Bjarne Oeverli (@bjarneo) (a806254)
  • fix(luaplugin): store the Lua providers in atomic pointers by Bjarne Oeverli (@bjarneo) (863b61d)
  • fix(lua): queue plugin controls so a plugin never waits on prog.Send by Bjarne Oeverli (@bjarneo) (3dd7b2e)
  • fix(lua): send volume, speed and mono controls to the Update loop by Bjarne Oeverli (@bjarneo) (70a7966)
  • docs: point the agent guide at providers.go for provider setup by Bjarne Oeverli (@bjarneo) (da28f71)
  • docs(url-scheme): say how long a cliamp:// link waits by Bjarne Oeverli (@bjarneo) (a0fe9a7)
  • refactor: test the exit resume save through saveExitResume by Bjarne Oeverli (@bjarneo) (0cd6073)
  • test: cover the resume saver of Jellyfin and Emby servers by Bjarne Oeverli (@bjarneo) (5a05900)
  • docs: say what providerSet finds without provider code by Bjarne Oeverli (@bjarneo) (3b6b161)
  • docs(site): list YouTube Music in the yt-dlp install note by Bjarne Oeverli (@bjarneo) (498c639)
  • test: move the built-in radio URL test into external/radio by Bjarne Oeverli (@bjarneo) (c99967d)
  • refactor: share one builder for the shuffle and mono commands by Bjarne Oeverli (@bjarneo) (da7dcee)
  • fix: list the terminal colors theme in cliamp theme list by Bjarne Oeverli (@bjarneo) (a681a4c)
  • refactor: put the V2 CLI client in ipc_client.go with a bounded wait by Bjarne Oeverli (@bjarneo) (d408134)
  • refactor: split run() into setup helpers by Bjarne Oeverli (@bjarneo) (759a39b)
  • feat: resume the Emby play context like Jellyfin by Bjarne Oeverli (@bjarneo) (a275273)
  • refactor: give Navidrome and Lyrion the same config wiring by Bjarne Oeverli (@bjarneo) (f0f3a75)
  • refactor: derive the --provider text from one key table by Bjarne Oeverli (@bjarneo) (7343c3b)
  • fix: start without a local provider when no config dir exists by Bjarne Oeverli (@bjarneo) (26b69ab)
  • refactor: build providers in providers.go by Bjarne Oeverli (@bjarneo) (e386f50)
  • fix(ytmusic): close the shared base from every YouTube provider by Bjarne Oeverli (@bjarneo) (057b122)
  • refactor(provider): move ProviderEntry to provider.Entry by Bjarne Oeverli (@bjarneo) (ccdabfd)
  • fix(ui/model): call the model method before the return reads m by Bjarne Oeverli (@bjarneo) (aa2f1f9)
  • docs: say that one failed remote argument drops all of them by Bjarne Oeverli (@bjarneo) (9f14d95)
  • fix(ipc): pass the canonical read method to the runtime owner by Bjarne Oeverli (@bjarneo) (f159c33)
  • docs: correct the save, vis and device notes for headless mode by Bjarne Oeverli (@bjarneo) (d111776)
  • fix(ui/model): name the provider list of an IPC load in the snapshot by Bjarne Oeverli (@bjarneo) (6a819bf)
  • test: send a real signal to the headless program by Bjarne Oeverli (@bjarneo) (5d2e8b5)
  • docs(radio): state the result cap of SearchStations by Bjarne Oeverli (@bjarneo) (c311eda)
  • docs(config): state which proxy variables ffmpeg reads by Bjarne Oeverli (@bjarneo) (fe25e4f)
  • docs(config): limit the unquoted list item rule to string lists by Bjarne Oeverli (@bjarneo) (32e034a)
  • fix(ytmusic): share only the transport with the Data API client by Bjarne Oeverli (@bjarneo) (75d2e01)
  • test(providers): pin the body limit of Plex, Lyrion and Audiobookshelf by Bjarne Oeverli (@bjarneo) (b04fb64)
  • refactor(tracksave): export NeedsDownload for the yt-dlp save check by Bjarne Oeverli (@bjarneo) (eed2e97)
  • feat(playlist): mark favorites section rows with PlaylistInfo.Favorite by Bjarne Oeverli (@bjarneo) (5ac2575)
  • fix: keep the headless visualizer in the layout by Bjarne Oeverli (@bjarneo) (5d6cdca)
  • feat(radio): add SearchStations, a station search with no pane state by Bjarne Oeverli (@bjarneo) (32ff5e4)
  • refactor: use theme.IsDefaultName for the theme saved at exit by Bjarne Oeverli (@bjarneo) (5b97514)
  • docs: state the track-start history rule in the history help by Bjarne Oeverli (@bjarneo) (67cd02c)
  • fix: cap the JSON bodies of radio, radiometa and lyrics requests by Bjarne Oeverli (@bjarneo) (c9c3c08)
  • refactor(ui/model): delete the V2 aliases that nothing can reach by Bjarne Oeverli (@bjarneo) (d3d5181)
  • docs(remote): state which provider_meta keys cliamp saves by Bjarne Oeverli (@bjarneo) (7e9f383)
  • docs(readme): match the setup wizard text to docs/cli.md by Bjarne Oeverli (@bjarneo) (a99ac61)
  • docs(yt-dlp): name Ctrl+S as the save key by Bjarne Oeverli (@bjarneo) (f761a9e)
  • docs(ssh): state the HOST forms that --ssh accepts by Bjarne Oeverli (@bjarneo) (071b15f)
  • docs(cli): add the --provider, --visualizer and --expand-playlist rows by Bjarne Oeverli (@bjarneo) (7456013)
  • test(ipc): cover the runtime.status alias in the server test by Bjarne Oeverli (@bjarneo) (2122869)
  • docs(site): list YouTube Music in the yt-dlp install note by Bjarne Oeverli (@bjarneo) (957c95b)
  • refactor(ipc): move the request structs that ui/model uses into it by Bjarne Oeverli (@bjarneo) (511665a)
  • docs: state which proxy variables cliamp reads by Bjarne Oeverli (@bjarneo) (71ee85d)
  • fix(ytmusic): send YouTube Data API calls through the NewAPI transport by Bjarne Oeverli (@bjarneo) (4823e91)
  • refactor(ui): drop the PanelWidth fallback of the visualizer width by Bjarne Oeverli (@bjarneo) (b74be26)
  • feat: run headless mode on the Model and delete the daemon by Bjarne Oeverli (@bjarneo) (a2732b2)
  • test(ui/model): drop an unused model value in a headless test by Bjarne Oeverli (@bjarneo) (dbb1bed)
  • fix(lyrion): name the provider Lyrion in the UI by Bjarne Oeverli (@bjarneo) (309e6af)
  • test(navidrome): test SaveAlbumSort with a fake config writer by Bjarne Oeverli (@bjarneo) (2bbdf85)
  • fix(ui/model): log the tracks that fail to play by Bjarne Oeverli (@bjarneo) (83a9c26)
  • feat(cmd): add provider_meta to cliamp history --json by Bjarne Oeverli (@bjarneo) (a7f0395)
  • fix(cmd): state the track-start rule in the empty history message by Bjarne Oeverli (@bjarneo) (ca1367c)
  • refactor(ytdlcookies): use playlist.NormalizeHost for cookie hosts by Bjarne Oeverli (@bjarneo) (3c6be9a)
  • fix(pluginmgr): download plugins through httpclient.NewAPI by Bjarne Oeverli (@bjarneo) (3e58eee)
  • fix(lyrics): send the shared cliamp User-Agent to LRCLIB by Bjarne Oeverli (@bjarneo) (132a015)
  • fix(resolve): find #EXT-X-ENDLIST past the HLS read cap by Bjarne Oeverli (@bjarneo) (18f20cc)
  • feat(resolve): add RemoteContext and DownloadYTDLContext by Bjarne Oeverli (@bjarneo) (06428fe)
  • fix(resolve): cancel the feed sniff with the URLContext context by Bjarne Oeverli (@bjarneo) (f64a52e)
  • fix(resolve): send feed, sniff and YouTube requests through NewAPI by Bjarne Oeverli (@bjarneo) (4ad29b1)
  • test(ui/model): port the headless daemon scenarios to the Model by Bjarne Oeverli (@bjarneo) (faa6fa4)
  • test(ytmusic): read the callback body in the sign-in retry test by Bjarne Oeverli (@bjarneo) (dc19700)
  • fix(spotify): close callback connections after each response by Bjarne Oeverli (@bjarneo) (2362401)
  • refactor(spotify): share the token lookup in Session.bearer by Bjarne Oeverli (@bjarneo) (550f4b5)
  • refactor: keep one live-stream rule in ui/model by Bjarne Oeverli (@bjarneo) (ff6a59f)
  • fix(ui/model): report the fields that headless mode reported by Bjarne Oeverli (@bjarneo) (0e2f998)
  • fix(spotify): send Web API calls through httpclient.NewAPI by Bjarne Oeverli (@bjarneo) (4e8fbb5)
  • test(spotify): give each test session its own Web API client by Bjarne Oeverli (@bjarneo) (972d05e)
  • fix(ui/model): keep the resume position on a media-control quit by Bjarne Oeverli (@bjarneo) (5a5e108)
  • test(qobuz): run scrapeCredentials and newClientSilent against httptest by Bjarne Oeverli (@bjarneo) (99161d7)
  • feat(ui/model): add a headless mode to the Model by Bjarne Oeverli (@bjarneo) (1721f69)
  • fix(providers): send streaming API calls through httpclient.NewAPI by Bjarne Oeverli (@bjarneo) (fed05ec)
  • fix(config): accept a # comment after a bracketed list by Bjarne Oeverli (@bjarneo) (85581ea)
  • test: fix 3 staticcheck findings in new tests by Bjarne Oeverli (@bjarneo) (4adf202)
  • fix: state that /dev/null on stdin still shows the yt-dlp prompt by Bjarne Oeverli (@bjarneo) (88fdbeb)
  • style(luaplugin): name queueVis in the Close queue comment by Bjarne Oeverli (@bjarneo) (4401232)
  • docs(plugins): state that exec can write outside the fs write rules by Bjarne Oeverli (@bjarneo) (2b205fe)
  • fix(luaplugin): name the recovery step for a bad trust manifest by Bjarne Oeverli (@bjarneo) (71ceb38)
  • fix(luaplugin): raise the render limit and log render timeouts apart by Bjarne Oeverli (@bjarneo) (b1a71ac)
  • test(luaplugin): give renders that must succeed a 1 s limit by Bjarne Oeverli (@bjarneo) (bc7839d)
  • fix(luaplugin): bound the queued event run in Close by Bjarne Oeverli (@bjarneo) (99ad11a)
  • fix(luaplugin): stop running Lua calls in Close by Bjarne Oeverli (@bjarneo) (7dc346b)
  • fix(luaplugin): queue visualizer init and destroy calls by Bjarne Oeverli (@bjarneo) (4060dda)
  • fix: accept y and yes at the yt-dlp install prompt by Bjarne Oeverli (@bjarneo) (c37035f)
  • refactor(ui/model): drop the unused IPC station search seam by Bjarne Oeverli (@bjarneo) (6c3fe2a)
  • fix(ui/model): use the saved rule only for queue rows in IPC bookmark by Bjarne Oeverli (@bjarneo) (9ef215f)
  • fix(ui/model): add up relative seeks during a yt-dlp seek by Bjarne Oeverli (@bjarneo) (b470fab)
  • fix(ytmusic): keep token refresh working after a browser sign-in by Bjarne Oeverli (@bjarneo) (85a0f12)
  • fix(ytmusic): close callback connections after each response by Bjarne Oeverli (@bjarneo) (977dc2e)
  • fix(ytmusic): bound the silent sign-in with a 30 s timeout by Bjarne Oeverli (@bjarneo) (92f1c89)
  • fix(embyapi): stop album paging when the server ignores startIndex by Bjarne Oeverli (@bjarneo) (8aa54d7)
  • style(luaplugin): write two new comments as plain sentences by Bjarne Oeverli (@bjarneo) (1870bf4)
  • docs(luaplugin): state that the plugin store is not secret by Bjarne Oeverli (@bjarneo) (7fa95cd)
  • fix(httpclient): let net/http dial SOCKS5 proxies for API clients by Bjarne Oeverli (@bjarneo) (31e8ca0)
  • fix(ytmusic): stop the sign-in wait when Google reports an error by Bjarne Oeverli (@bjarneo) (d005613)
  • fix(luaplugin): reject an unknown type in plugin.register() by Bjarne Oeverli (@bjarneo) (2354b96)
  • refactor(config): drop the YouTube Music fallback credentials hook by Bjarne Oeverli (@bjarneo) (cf81f89)
  • fix(luaplugin): fold path case with Unicode rules in the write check by Bjarne Oeverli (@bjarneo) (aed6cd8)
  • docs(cli): list the Qobuz, Tidal and YouTube Music reset commands by Bjarne Oeverli (@bjarneo) (bfc9714)
  • fix(ui): start source resolver tracks off the Update goroutine by Bjarne Oeverli (@bjarneo) (ff6c062)
  • test(luaplugin): keep the write rule test home in the temp dir by Bjarne Oeverli (@bjarneo) (8ae96e7)
  • fix(luaplugin): drain exec output after a line longer than 1 MiB by Bjarne Oeverli (@bjarneo) (e24c69d)
  • fix(luaplugin): never block the UI goroutine in RenderVis by Bjarne Oeverli (@bjarneo) (a019827)
  • fix(luaplugin): bound the top-level chunk of a plugin at load by Bjarne Oeverli (@bjarneo) (c1819a1)
  • fix(luaplugin): log callback errors only to plugins.log by Bjarne Oeverli (@bjarneo) (1c8cff2)
  • fix: ask before a yt-dlp install only in an interactive start by Bjarne Oeverli (@bjarneo) (414fc61)
  • test(ui/model): check the EQ save of the IPC settings table by Bjarne Oeverli (@bjarneo) (d613f10)
  • fix(ui/model): search stations over IPC without the pane search state by Bjarne Oeverli (@bjarneo) (cd0eeb1)
  • fix(ui/model): filter picker targets only through PlaylistTargetFilter by Bjarne Oeverli (@bjarneo) (0d91304)
  • feat(config): add typed save methods to SaveFunc by Bjarne Oeverli (@bjarneo) (39247bc)
  • refactor(ui/model): identify Local and Radio by provider key by Bjarne Oeverli (@bjarneo) (bfd527d)
  • docs(themes): show the real theme skip log line by Bjarne Oeverli (@bjarneo) (b829639)
  • 206 older commits are not listed. The full changelog link below shows all commits.

Checksums (SHA256)

836d0ed3d46a39ea0ff75b17738e77c2652c03fbc46aefb78110cb6664a41ee6  cliamp-darwin-amd64
f12a36efe27d8eaaf1ab489be2270850bea4a0f63f694cc1688693bf13e256b4  cliamp-darwin-arm64
2ee17d8f613d9dd23d124b8f5580111610f5aa396b20f2818e388f7b7a227152  cliamp-linux-amd64
4e686e9b5188030bd3382c7fac997077bbdff8953fbab0003c49874b5f9ea1fc  cliamp-linux-arm64
7a8dee25e6b3b1ae20ce5f1d656decb0d5eb128201650f626c7ce772bf070811  cliamp-windows-amd64.exe
2f98eb4f968d603dadf0d68ef50a28104f2b7d7a0d01a55a49547bf9ba91dbcb  cliamp-windows-amd64.zip

Full Changelog: v2.3.0...v2.4.0