Quill Radio 2.0 -- Release Notes

Quill Radio 2.0 is about one thing done thoroughly: recordings you can trust. Version 1.1.0 rebuilt the sound -- a new playback engine, every stream format, live rewind, richer Sound Enhancements. 2.0 turns that same care on the recorder, closing a reported round of recording bugs and adding the one piece that was always missing: a recording that survives a restart. If you schedule shows, leave long recordings running unattended, or have ever come back to find a capture cut short or gone entirely, this release is for you.

It also widens the net for finding stations: iHeart and TuneIn now join the search, so two of the biggest directories on the internet are searchable and playable right inside Browse Stations. More on that below.

As always, everything below also lands in QUILL itself. Quill Radio and QUILL share one codebase and one data store, so these fixes arrive in both at once -- nothing here is vendored into the Quill Radio wrapper.

Update 2.2.0

Quill Radio 2.2.0 collects everything since 2.1.2 -- a round of fixes and small conveniences straight from your testing, and a piece many of you have asked for: a proper backup you can carry to a new device.

Update 2.1.2

Quill Radio 2.1.2 is a quick fix-up for three things you reported -- two of them from 2.1.1 itself. Thank you for the fast, specific feedback; it is exactly what makes these turnarounds possible.

Update 2.1.1

Quill Radio 2.1.1 is about weather radio done properly, and about a kind of station that matters enormously to this community and has never been easy to find: the radio reading service.

Both directories follow the same rules as every other source: live pulls are off in Safe Mode, every network call is in the egress audit, and a bundled snapshot keeps the feature honest when the network is not there.

Two more from live feedback:

Update 2.1.0

Quill Radio 2.1.0 adds a top-level Weather menu, a whole new way to browse stations, one-click updating, and a round of fixes from live feedback -- all in the shared quill package, so QUILL gets them too.

Update 2.0.2

Adds concurrent recording, live Sound Enhancements preview, OptiLab broadcast polish, fixes the 2.0.1 channel mode, and adds two favorites features people asked for:

Update 2.0.1

A fast follow-up from the first round of live feedback, folded into this same release:

The headline: recordings you can trust

A recording in progress now survives a restart -- and Quill Radio asks before resuming

This is the one that hurt. You set a recording going, the app quits or crashes (or Windows does), and the recording is just gone -- the FFmpeg process it had started keeps writing to a temp file nobody would ever find.

Quill Radio now remembers an in-progress recording. It writes a small marker when a recording starts and clears it on a clean stop, so a crash leaves a breadcrumb. On the next launch it first tidies the temp folder -- any finished orphan file is moved into your recordings folder where you'll actually find it, while a file still being written is left untouched -- and then, if a recording was in progress and is still within a 10-minute grace window, it asks you, once, in a proper accessible dialog:

A recording of WQXR was in progress until 9:00 AM. Resume it for the remaining 12 minute(s)?

Resume (Enter) restarts the recording for the remaining minutes only -- not a fresh full duration. Skip (Escape) leaves it as it is. A Don't ask me again checkbox remembers your choice -- always resume, or never ask -- and you can change it later in Preferences. Nothing happens when nothing was in progress, and a marker file that has gone corrupt is thrown away rather than driving a bogus resume.

Scheduled recordings fire reliably throughout their window, not just at the exact minute

The scheduler used to match the exact start minute. So a recording set for 8:00 that Quill Radio only reached at 8:01 -- a slow launch, a brief stall, the tray icon taking a moment -- silently never fired, and a start that failed still burned the whole occurrence for the day.

The scheduler now treats an entry as due from its start time through the end of its duration, so a late arrival starts with the remaining minutes and catch-up on launch is free. Last-fired is stamped only on a successful start (a failure retries on the next poll while the window is still open), one-time entries auto-disable once they've fired, and when two schedules are due in the same minute while the recorder is busy, the second is held and announced instead of being burned. The scheduler thread itself is now lock-guarded and wrapped so it can no longer die silently.

The Recordings list stops flickering and keeps your place

The Recordings list used to rebuild itself on every refresh, snapping a screen reader back to the top and losing whatever you'd selected. It now updates rows in place, keyed by file path: a no-op when nothing has changed, and when something has, your selection, focus, and scroll position are all preserved instead of the list rebuilding under you mid-read.

The counts are honest now, too. The active recording is counted from the recorder itself, so a recording writing to a temp folder is no longer invisible in the list; a firing schedule is no longer double-counted; and completed one-time entries drop out of the scheduled count. The active row shows a live elapsed time, scheduled entries show their zone-labeled times, and the tray tooltip carries "(recording)" while a capture is running.

Recordings harden against dropped connections, dead streams, and a crashed host

Four pipeline fixes that together make a long unattended recording far more likely to come out whole.

Browse Stations used to search the community RadioBrowser directory and the free SomaFM directory. 2.0 adds two of the largest directories on the internet -- iHeart and TuneIn -- blended into the same results list, so a search for a call sign, a city, or a show now reaches far more of the stations people actually ask for. Every result is labeled with where it came from (iHeart, TuneIn, RadioBrowser, SomaFM), and you play it the same way you always have.

Both are keyless and need no account. iHeart is read straight from its public station sitemap -- a two-request directory index -- and a station's real stream is resolved on demand from its own page the moment you play it, never by bulk-fetching thousands of pages. TuneIn goes through RadioTime's open OPML directory (the same service TuneIn's own web player uses): search returns matching stations and the stream address is looked up only for the ones about to play. To keep a single search from turning into dozens of network round trips, iHeart and TuneIn each resolve a small, capped handful of the most relevant matches per search -- enough to add immediately-playable results without slowing the list down -- while RadioBrowser keeps paging as before. A Refresh button re-fetches the iHeart directory index (it is cached once per Browse Stations session; TuneIn and RadioBrowser are always live).

With four directories in one list, Browse Stations gained the controls to steer it. A Source dropdown lets you narrow the search to just one directory -- All sources, RadioBrowser, iHeart, TuneIn, SomaFM, ACB Media, or Website -- when you already know where a station lives. And the old free-text tag and country boxes are now proper dropdowns: a Tag/genre list and a Country list, filled in from the directory itself, so you pick "jazz" or "United Kingdom" from a list instead of guessing the exact spelling, and choosing one runs the search right away.

TuneIn also feeds Find Streams from a Website: paste a TuneIn station page and Quill Radio resolves its real playable stream, the same on-demand lookup the directory search uses. Find Streams now also recognizes an iHeart or TuneIn page directly rather than handing back a page address that will not play.

Like every other network feature, iHeart and TuneIn are off in Safe Mode, HTTPS-only, and inventoried in QUILL's network-egress audit. This lands in the shared quill package (core/radio/iheart.py, core/radio/tunein.py, core/radio/directory_search.py), so QUILL and QUILL Cast gain the same reach.

Scheduling recordings gained real editing

The Schedule Recording dialog was capture-and-forget: add an entry, and your only other move was to delete it. 2.0 makes the schedule something you can actually manage.

What's Playing reaches more stations

When a station will not answer the usual title request -- and after Quill Radio has already tried the playback engine's own title channel -- it now takes one more step: it reads the station's own public "now playing" status page (the Icecast or SHOUTcast status endpoint the stream's own server publishes) and pulls the current title from there. It only ever talks to the same server you are already listening to, and it is off in Safe Mode. The practical result is a real "Now playing" on a batch of stations that used to answer with silence.

For troubleshooting: verbose logging and a log folder you choose

Two additions for when something needs diagnosing. Preferences (Ctrl+,) gained a Verbose logging checkbox that turns on detailed debug logging live, without a restart, and a Log folder setting so you can point the log somewhere easy to find (and hand to a bug report). Recording problems now capture the recorder's own error output into that log as well, so a failed capture leaves a trail instead of a mystery.

Built on the 1.1.0 base

2.0 stands on everything 1.1.0 delivered, and none of it changes:

See release-notes-1.0.md for the 1.0 and 1.1.0 story in full, and CHANGELOG.md for the complete versioned history.

Known notes for this release

Not a fork -- a guarantee

Quill Radio runs the exact same radio feature code as QUILL, from the same upstream package. The recordings overhaul in this release lands once, in the shared quill package, and reaches QUILL, Quill Radio, and QUILL Cast together. This repository carries only the wrapper, the installer, the icon, and these docs.