Skip to content

13.14.0

Choose a tag to compare

@github-actions github-actions released this 13 Sep 23:02

Changelog

Changes in v13.13.8..HEAD:

Highlights

  • SpotiFLAC Source Support — Hush can now resolve and play tracks from Spotify-mirror sources through the upstream SpotiFLAC runtime, with lossless (FLAC) downloads across multiple providers, a user-ordered source priority, automatic fallback, and self-renewing per-source verification. (Hush)
  • Native Musixmatch Lyrics Provider — added as a first-class lyrics provider with per-provider priority selection, alongside the existing PAXsenix Musixmatch and other sources. (Hush)
  • Equalizer AutoEq Profile Import — import AutoEq measurement profiles directly into the parametric EQ, with saved-profile apply and management. (Hush)
  • Separate Downloads and Cache Locations — downloads and cache are now distinct, independently relocatable folders. Downloads keep the source's real file extension; cache holds fragments. Custom location choices now persist across restarts. (Hush)
  • Self-Healing Cipher Config — the remote player config now reads the ZemerTeam zemer-cipher synced config schema with per-player entries and aliases, plus manual refresh and a size guard. (Hush)

SpotiFLAC Source

  • Native Go runtime bridge — SpotiFLACNativeRuntimeBridge drives the upstream SpotiFLAC Go runtime (app/libs/gobackend.aar) for extension discovery, signed requests, and downloads. Builds without the AAR degrade gracefully instead of crashing. (Hush)
  • Source priority ordering — SpotiFLACQualityCascade lets you order which source is tried first and fall back through the rest, so a source that lacks a track no longer ends playback. (Hush)
  • Per-source quality cascade — when a source reports no compatible lossless quality, it is retried at a quality token its own manifest declares (e.g. HIGH for tidal-web, best for YT Music) instead of a hardcoded value no source accepts. (Hush)
  • Every enabled source is actually attempted — a hardcoded retry quality that silently re-asked the same question and a sweep budget sized for the old chain both caused sources to be skipped. The budget is now derived from the real work (SpotiFLACQualityCascade.sweepBudgetMs). (Hush)
  • Per-provider stall watchdog — SpotiFLACProviderStall abandons a wedged provider quickly instead of consuming the whole sweep budget. Liveness is now item-scoped, so an unrelated concurrent download can no longer keep a stalled provider looking alive. (Hush)
  • Persisted stall demotion — providers that stall are demoted to the back of the chain, and that memo now survives process restarts, so a cold start no longer leads with a provider that always wedges. (Hush)
  • Sweep verdicts and miss memo — SpotiFLACSweepVerdict distinguishes a genuine no-match from an unfinished sweep, and SpotiFLACMissMemo caches a real miss so it is not re-swept on every replay. (Hush)
  • Self-renewing verification — SpotiFLACSessionRenewWorker renews per-source signed sessions in the background, so a rotated or expired gateway session no longer forces a manual Cloudflare check mid-playback. (Hush)
  • Extension package integrity and signing — SpotiFLACExtensionPackageVerifier, SpotiFLACExtensionKeyStore, and SpotiFLACExtensionPackageStore verify downloaded extension packages before they are used, with dynamic registry updates. (Hush)
  • Playback cache with real integrity checks — SpotiFLACPlaybackCache and SpotiFLACFileIntegrity validate a cached file on its recorded size and container signature (FLAC/Ogg/ID3/ftyp/WebM/MPEG). Truncated downloads and gateway error pages written to the audio path are discarded and re-swept instead of being served as audio. (Hush)
  • Single copy on disk — a resolved SpotiFLAC file is served directly rather than being copied into media3's cache, so a track no longer occupies two copies. (Hush)
  • Corruption recovery — a cached file that verifies but will not decode (ERROR_CODE_PARSING_CONTAINER_MALFORMED, DECODING_FAILED) is discarded and every source is walked again, bounded by the existing retry budget. (Hush)
  • In-flight download guard — a file currently being rewritten is never mistaken for damage or evicted, and user-downloaded (pinned) files are never auto-deleted. (Hush)
  • Download origin tracking — DownloadOriginStore records which source a track came from, so a download is fetched from the same source the track plays from. (Hush)
  • Verification overlay — SpotiFLACVerificationOverlay surfaces per-source verification progress in-app instead of a bare source error. (Hush)

Playback and Source Routing

  • Single resolution path — PlaybackDataSourceRouting, PlaybackEngineOrder, and SchemeRoutingDataSource consolidate the previously duplicated SpotiFLAC-first / YouTube-first resolution paths into one. (Hush)
  • Fallback to YouTube is conditional — the fallback option is only offered when YouTube streaming is enabled, and honours the source toggles on the real stream-resolution path. (Hush)
  • No playable source handling — NoPlayableSourceException plus a one-tap "play this one from YouTube" action, so a genuine miss is actionable rather than a dead error. (Hush)
  • No more silent skipping — TransportSkipPolicy prefers trying every enabled source before advancing, rather than skipping the track. (Hush)
  • Accurate source labelling — PlaybackSourceInfo reports whether a track is served from the SpotiFLAC cache, a live SpotiFLAC download, or a YouTube stream, shown distinctly from media3's own downloaded badge. (Hush)
  • Playback download progress — PlaybackDownloadProgress shows download progress in the player, so it is clear when a track is still downloading. (Hush)
  • Queue persistence — the playback queue and position are committed when the app goes to the background, so any close path preserves them and a cold start resumes correctly. (Hush)
  • Next/previous no longer dead on restore — restoring a persisted queue now yields a usable timeline before a new playlist is chosen. (Hush)

Downloads and Storage

  • Downloads / cache separation — DownloadedFileStore, DownloadedFileLocation, and DownloadNaming keep downloads and cache as separate roots with separate migration and cleanup rules. (Hush)
  • Custom location persistence fix — a custom download or cache directory now survives an app restart instead of silently reverting. (Hush)
  • Folder hygiene — DownloadFolderHygiene avoids leaving stray partial files and duplicates in the downloads root. (Hush)
  • Shared cache limit — the SpotiFLAC cache shares the app's Storage settings limit rather than duplicating its own size and clear controls; usage is shown next to the max song cache size. (Hush)

Lyrics

  • Native Musixmatch provider — MusixmatchLyricsProvider with in-app client, registered in LyricsHelper and selectable in the lyrics provider priority list. (Hush)
  • Priority provider selection — LyricsProviderPriority gained the Musixmatch toggle so ordering between providers is user-controlled. (Hush)

Equalizer

  • AutoEq import — import AutoEq measurement profiles into the parametric EQ (AutoEqImporter + in-screen import dialog). (Hush)
  • Saved profile management — custom profiles are selectable and applyable, with active-profile tracking. (Hush)

Cipher / Player Config

  • Zemer synced config schema — RemoteCipherConfig now parses schemaVersion and a players map (signature function, throttling class, signature timestamp, aliases) with per-player lookup by hash or alias. (Hush)
  • Effective signature timestamp — signature timestamp resolution uses the per-player config when available and falls back to the local value. (Hush)
  • Manual refresh + size guard — CipherConfigFetcher.refreshNow() and a maximum config size, so a bad remote payload cannot break resolution. (Hush)

Waze Bridge

  • Reconnect policy — WazeReconnectPolicy (with unit tests), WazeBootReceiver, and the reconnect receiver make the bridge recover automatically when Waze's SDK service restarts mid-session. (Hush)
  • Reliable package resolution — HushPackageResolver detects the active Hush process instead of relying on installed-package presence, fixing shim↔app signature/connection mismatches. (Hush)
  • Queue reliability — queue revisions and a content fingerprint ensure the Waze queue is republished when it actually changes, including after a player restart or playlist switch. (Hush)
  • Metadata hot-path fix — the queue bundle is no longer rebuilt and re-broadcast on every metadata tick; it is cached behind an allocation-free fingerprint, with a retention cap for very large queues. (Hush)
  • Regenerated shims — waze-shims.zip rebuilt and synced to both main and mobile asset directories. (Hush)

Performance and Memory

  • Lower-RAM search — OnlineSearchSuggestionViewModel, CachePlaylistViewModel, and App/AppMemoryPolicy changes reduce allocation during repeated searches and trim work on low-RAM devices. (Hush)
  • Faster first playback — removed the duplicate first-track resolution requests and the startup gating that delayed initial playback. (Hush)
  • Visualizer fix — the PulseMatrix visualizer now emits real FFT band data (verified: 16 non-zero bands, fftAge 0–76 ms) and correctly drops to zero when paused. (Hush)
  • Source-label marquee — new shared Modifier.hushMarquee() scrolls long codec/source labels indefinitely instead of truncating them, and stays still when the label fits. (Hush)

Build / CI

  • gobackend.aar required and verified — CI asserts app/libs/gobackend.aar is present and contains libgojni.so before building, so a missing SpotiFLAC runtime fails fast instead of shipping a silently degraded app. (Hush)
  • Musixmatch module shipped via overlays — the Hush-only lyrics/musixmatch module (including its build file) is packaged through overlays/lyrics and scripts/apply-submodule-patches.sh, so CI reconstructs it from the repository alone rather than depending on an untracked submodule checkout. (Hush)
  • Release AAR build script — scripts/build-spotiflac-aar.sh documents and automates rebuilding the Go runtime AAR with the upstream toolchain. (Hush)
  • Verification scripts — added scripts/waze-bridge-smoke-test.sh, scripts/verify-spotiflac-single-copy.sh, and scripts/hush-performance-benchmark.sh. (Hush)
  • ProGuard rules — added keeps required by the new runtime and routing paths. (Hush)

Housekeeping

  • Version bumped to 13.14.0 (versionCode 170, app + waze-shim). (Hush)
  • Unit tests pass (all green), including new suites for the SpotiFLAC sweep verdicts, quality cascade, provider stall, file integrity, playback cache, session renewal, source auth, auto-verifier, playback routing, engine order, transport skip policy, download naming, and Waze reconnect policy. (Hush)

Upstream credits

Hush is built on ArchiveTune and combines features, fixes, and UI from several open-source YouTube Music clients—including Metrolist, Vivi Music, and Echo Music. Those projects are credited below; their licenses and copyright notices are preserved in source.

Project Repository
ArchiveTune ArchiveTuneApp/ArchiveTune
Metrolist metrolistgroup/metrolist
Vivi Music vivizzz007/vivi-music
Echo Music EchoMusicApp/Echo-Music
SpotiFLAC spotiflacapp/SpotiFLAC-Mobile
Zemer Cipher ZemerTeam/zemer-cipher

Thank you to the maintainers and contributors of every project listed above.