1.29.0 (2026-10-31)
Features
- admin: show a Keenable key that lives only in .env (#2148) (691cedd)
- app: edit or remove a saved station login, and say when it's rejected (#2119) (cc103c9)
- app: keep a playback log in store builds that a listener can share (#2156) (8864876)
- queue: length and air-time forecast on /state queue items (#2146) (fb62a2f)
- search: Keenable as a web-search backend (#1902) (d996919)
- stats: rebuild the Stats page as a numbered front page with a weekly recap (#2123) (82e31b1)
- stats: replace the numbered section rules with a tuner dial (#2167) (de09d8f)
- transitions: optional equal-power curve for plain crossfades (#2002) (4dd559a)
- web: group the provider pickers by kind, gateways as one-line rows (#2126) (46de52e)
Bug Fixes
- admin: count wrong guesses, not requests, and let the operator turn the lockout off (#2165) (b41a344)
- admin: refuse a key with a control character before probing it (#2145) (bc17397)
- app: abort a stalled station body at its deadline, and let a caller's abort reach it (#2172) (c92f5f9)
- app: close the playback log's redaction gaps, and let no log line cost playback (#2171) (d0927da)
- app: give every station body read a deadline, and rename refusalBody (#2174) (f0d4432)
- app: keep checking a stuck station login, and refuse only on a Basic challenge (#2137) (66c1ce6), closes #2114
- app: keep only Apple's port types in a route line (#2173) (a1ecde6)
- app: keep re-checking a stuck station password, and forget it only on the controller's refusal (#2152) (65b44d3)
- app: re-send the lock-screen card only when it changes, and probe the live dot with the saved login (#2151) (247a21d)
- app: reload the live stream only when its media clock has stalled (#2121) (b3f2fa1)
- app: send a remote Play through the stream recovery, and back off a hung reload (#2155) (73a4959)
- app: send the lock-screen cover on an item's first playing, not at load (#2168) (1ac76b7), closes #2162
- app: stop the synced lyrics crashing the app on Android (#2100) (45725ad)
- broadcast: advertise the rendered listener buffer, and hand Liquidsoap the burst's bitrate (#2158) (2411ffa)
- broadcast: harden the marker writers and the bitrate handoff, in both scripts (#2170) (b83dde7)
- broadcast: read radio.liq's Opus encoder the way the CBR test does, in both scripts (#2175) (00a7eeb)
- controller: wake an idle station within a second of a listener tuning in (#2109) (9394ecd)
- dj: stop naming a compilation's title as the song's album (#2120) (4cc9ada), closes #2117
- dj: stop the location grounding naming a place the operator dropped (#2110) (cd7977f)
- liquidsoap: encode the Opus mount as hard CBR so its burst is time-sized (#2157) (fd35a85)
- llm: fail over when Gemini says "models/<id> is not found" (#2108) (b3244f0)
- llm: retry OpenRouter's "reasoning is mandatory" rejection at minimal effort (#2107) (1bea8b6)
- pin the /station-auth contract, read radio.liq's comments in the Opus check, and cover the playback log in the privacy policy (#2169) (2def860)
- providers: AI Gateway onboarding test, Requesty Test key, Keenable key copy (#2122) (60d5dd0)
- providers: small follow-ups from the provider catalogue PRs (#2135) (84d8f93)
- requests: stop refusing dedications as unsupported conditions (#2149) (572cbf2), closes #2133
- settings: strip control characters from a secret as it is saved (#2153) (da39505)
- tts: expand £/€ amounts, clock meridiems and No. into spoken forms (#2104) (6bd7444), closes #2103
- tts: level Chatterbox, build the tts-heavy sidecar on arm64, update PocketTTS to 4.0.1 (#2105) (81275f6)
- web: ask again about a saved station password while the player is stuck (#2186) (7b41c8f)
- web: keep the station password prompt above every skin, and lock the skin beneath it (#2187) (b6f2eab)
- web: make the listener drawer and top bar opaque wherever their blur is stripped (#2147) (655149e), closes #2132
- web: reconnect after the stream ends, and keep watching a stall (#2188) (bad6ef8)
- web: size provider card columns by group, against the picker's width (#2154) (a0fbb50)
- web: skip a woken station's stale idle silence on tune-in (#2125) (1fd51ee)
- web: trust only the controller's answers at the station gate, and keep a password it can't check (#2176) (5f61612)