feat: 0.9.10 — Tidal/Qobuz fallback via qobuz.kennyy.com.br + perf wins
Adds qobuz.kennyy.com.br as a second LosslessSource alongside
qobuz.squid.wtf. When squid is down (captcha-required 403s, operator
account issues, etc.), the registry now falls over to a different
operator's Qobuz proxy automatically — both deliver lossless FLAC.
The original v0.9.10 design (committed as MonochromeSource hitting
api.monochrome.tf) was based on a wrong assumption: Tidal's API
returns Widevine-encrypted DASH for all tracks, and account-banning
across the squid.wtf/hifi-api ecosystem made the Tidal-side path
non-functional. After probing Monochrome's web UI flow, we
discovered Monochrome internally routes downloads through Qobuz
proxies via ISRC lookup. The user's configured Qobuz instance is
qobuz.kennyy.com.br — a near-clone of qobuz.squid.wtf's Qobuz-DL
codebase running under a different operator with NO captcha gate.
This release:
- KennyyApiClient: HTTP client for qobuz.kennyy.com.br. Same
/api/get-music + /api/download-music endpoints as squid.wtf,
same {success, data} response envelope. No captcha interceptor
(this instance is unauthenticated). - KennyySource: implements LosslessSource. id="kennyy_qobuz".
Reuses QobuzModels (identical JSON shape across Qobuz-DL
deployments) and QobuzSource's scoring helpers. - KennyyModule: Hilt @IntoSet binding.
- LosslessSourcePreferences.DEFAULT_PRIORITY = [squid_qobuz,
kennyy_qobuz] for fresh installs. Existing users with explicit
priority preserved.
Performance optimizations (~3x speedup vs original baseline):
- QobuzSource: track lastKnownBadCookie. isEnabled() returns false
when (a) circuit-broken, (b) cookie blank, (c) cookie matches the
last value that returned a captcha-required 403. Implicit reset
when user pastes a fresh cookie. Saves ~16s/track for users
with squid down or no captcha set. - AggregatorRateLimiter: kennyy_qobuz pre-configured to 1 token /
3 seconds, burst 4 (3x default). Auto-backoff: if a source hits
5+ 429s in 60 seconds, halve its tokensPerSecond (floor 1/min).
Self-tunes toward operator's actual threshold instead of
hardcoding our guess. - TrackDownloadWorker: PerfSummary log line at end of doWork
with tracks/seconds/tracks-per-minute. Greppable for empirical
before/after measurement. - QueueTrace diagnostic logs on download_queue inserts (DiffWorker)
and consume-time duplicate detection (TrackDownloadWorker) for
future debugging if duplicate-queueing recurs.
Measured on a real sync: 70 tracks in 8m 1s = 8.7 tracks/min,
vs prior ~2.7 tracks/min baseline. ~3.2x faster.
Specs: docs/superpowers/specs/2026-05-03-monochrome-source-design.md
(historical — describes the original Tidal-side design before the
pivot)
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Install
Download the .apk below and open it on your Android device. If you've got a previous Stash release installed, this upgrades in place — your library, sync history, and settings are preserved.
Requires: Android 8.0 (API 26) or newer.
See the README for first-time setup.
Full Changelog: v0.9.9...v0.9.10