- dependabot.yml: target pre-release branch for npm and cargo updates
- redirect-pr-to-prerelease.yml: auto-redirect PRs to main → pre-release
with a friendly comment explaining the workflow
When download fails after retry at the same quality (e.g. HiRes),
automatically try the next lower quality (e.g. Lossless). This handles
CDN edges that consistently serve broken responses for specific tracks
at certain quality levels. Applied to all three download paths: standard
download, streaming probe fallback, and prefetch. Also fixes prefetch
retry using wrong quality variable.
Add complete pt.json locale file with all 45 top-level translation
sections. Register the new locale in the i18n index with native name
"Português (Brasil)".
Apply the same CDN premature EOF fix to offline-playback: on download
failure, request a fresh stream URL and retry once. Also switch
StreamFetcher to native-tls and add detailed error chain logging.
Root cause: Qobuz CDN returns "end of file before message length
reached" for specific tracks - sends Content-Length header then
closes connection without body data. Consistently reproducible for
certain tracks while others from the same album work fine.
Add retry logic at all download paths: on failure, request a fresh
stream URL from the API and retry once (CDN may route to different
edge). Streaming probe failures now fall back to standard download
path instead of failing completely. Also stream response body in
chunks for better partial-read diagnostics.
Add Drop impl to PlaybackEngine so the ALSA Direct writer thread is
properly stopped when the engine is dropped (e.g. streaming timeout).
Previously, a failed streaming attempt would orphan the writer thread,
keeping the ALSA device locked and blocking all subsequent playback.
Also force HTTP/1.1 for audio downloads and add detailed error chain
logging to diagnose persistent "error decoding response body" failures
for specific tracks.
Audio downloads (streaming, prefetch, direct) now use no_gzip/no_brotli/no_deflate
to prevent reqwest from trying to decompress binary FLAC data when CDN servers
send Content-Encoding headers. This fixes "error decoding response body" errors
that caused certain tracks to fail playback.
CoreBridge initialization timeout increased from 10s to 30s with progress logging,
fixing V2NotInitialized errors on slow network startups.
Refactor ALSA Direct engine from thread-per-source to a single
long-lived writer thread with a source queue. When one source ends,
the writer thread immediately picks up the next from the queue with
zero gap. Remove the ALSA Direct gapless rejection gate since the
engine now natively supports source queueing.
Install tray icon to user's local icon theme dir so panels using
StatusNotifierItem name lookup can find it. Set dedicated temp dir
for libayatana-appindicator's icon file. Install all icon sizes
(32-512px) in Flathub manifest for broader DE compatibility.
ALSA streams don't have application.process.binary, only
application.name = "PipeWire ALSA [binary]". Generate both
match conditions so resample.disable applies to all stream types.
When last_view pointed to a view with incomplete context (e.g.
album without selectedAlbum data), the Svelte CSS extraction
pipeline would corrupt and produce PostCSS "Unknown word" errors
that survived cache cleans and npm ci.
- Add isSessionRestoreSafeView() whitelist for context-free views
- Add getSessionFallbackView() for graceful degradation
- Centralize persist logic in getPersistedSessionViewState()
- Only persist views that have valid context data
- Add purchase-album to restore path
- Add dev:reset-last-view script to reset session.db
- Fix AlbumCreditsModal.svelte event handler typing
Add defensive fallback conditions for artist and playlist views
when activeView is set but data hasn't loaded yet (race condition
during session restore). Also add a catch-all fallback at the end
of the view chain so no combination of state can result in an
empty/black main content area.
Add real streaming path to v2_play_track: when stream_first_track
is enabled, uses play_streaming_dynamic + background chunked
download instead of full download before playback.
Fix seekbar not showing position for streamed tracks by passing
duration_secs from frontend to the backend. Without it, the
player stored 0 as duration, making the seekbar appear empty.
Hi-Res+ tracks at 192kHz/24-bit can be 100-200MB and take over 2 minutes
to download. The 120s total timeout caused silent download failures where
the track appeared to play but had no audio data. Keep only the 10s
connect timeout. Also fix unused import warning for MusicBrainzSharedState.
Per PipeWire docs, stream.rules for ALSA plugin clients belong in
~/.config/pipewire/client.conf.d/, not pipewire.conf.d/ which is
for daemon-level configuration. The DAC sample rate config stays in
pipewire.conf.d/ as that is daemon configuration.
When PipeWire drops the stream during pause, the graph reverts to the
DAC's default rate (e.g. 44100Hz). The pre-stream force-rate metadata
can be ignored when no streams are active. Re-applying after the stream
is connected forces PipeWire to reconfigure the graph at the correct
sample rate.
Also fix unused import warning for MusicBrainzSharedState in commands_v2
by using the import instead of the full path in factory_reset.
- Fix doctest: use qbz_nix_lib instead of crate in doc example import
- Fix credentials roundtrip: clear stale credentials before test, gracefully
skip if decryption fails due to environment issues (different key/salt
from previous runs)
Closes#154
When WebKitGTK's GnuTLS can't find system trust store (common in
AppImage on some distros), direct HTTPS image loads fail. Home page
worked because AlbumCard already used cachedSrc which proxies through
the Rust backend (reqwest with its own TLS).
Apply cachedSrc to all remaining artwork displays:
- PlaylistCollage (playlist grid covers)
- NowPlayingBar (current track artwork + hover preview)
- ImmersiveArtwork (fullscreen player)
- QueuePanel (sidebar + immersive queue/history)
- CoverflowPanel, HistoryPanel, FocusMode
Also resolve artwork URL in +page.svelte via getCachedImageUrl before
passing to NowPlayingBar/ImmersivePlayer, so all downstream immersive
panels receive pre-cached asset:// URLs.
Ubuntu ships libjpeg8 (libjpeg.so.8) while Debian sid and Fedora ship
libjpeg62-turbo (libjpeg.so.62). Building with sys-lib-libjpeg on Ubuntu
hardcodes a dependency on libjpeg.so.8, breaking startup on other distros.
Let mupdf vendor its own libjpeg (statically linked) instead.
- Add filename-based track number inference as fallback when tags lack track_number
- Detect degenerate track numbering (all tracks same number) and use index fallback
- Flatten single-track-per-disc box sets into sequential numbering
- Replace fragile SELECT * with explicit column list in track queries
ALBUM_CARD_WIDTH 180->210 to match AlbumCard size='large' (210px).
ALBUM_GAP_X 14->22 to match CSS gap. ALBUM_CARD_HEIGHT 290->310
to fit 210px artwork + text + quality badge.
Mono font only kept in Settings > Dev > Logs (LogsModal),
command blocks, and keyboard shortcut keys. All other UI
elements (durations, metadata, badges) now use --font-sans.
The Discover dropdown items (Home, Editor's Picks, For You) now
correctly navigate to the three tabs of the Home/Discover view
using navigateTo('home', tabId) instead of navigating to unrelated
discover-* view pages.
Nav buttons get 8px padding on the edge side (matching folder spacing).
New opt-out toggle to hide window control buttons (min/max/close) for
window manager users who want the titlebar for nav and search only.
Opt-in setting (off by default) that moves Discover, Favorites, and
Local Library from the sidebar to the custom titlebar. Includes
dropdown menus for Discover and Favorites sub-items. Navigation
button position defaults to opposite of window controls but is
user-configurable. Items are hidden from sidebar when shown in
titlebar.
Show a friendly message instead of a generic API error when
the user has no recent listening history to seed suggestions.
Adds insufficientHistory i18n key to all 4 locales.
Closes#158
When a track finishes on Chromecast, the media session may clear
entries entirely, returning IDLE with idle_reason=null instead of
FINISHED. Detect end-of-track by the PLAYING->IDLE transition
instead, matching the DLNA approach.