Skip to main content

← All posts

Release Notes

Playbill v0.1: One Image, Many Sources

· 7 min read

Nine days ago Playbill was a build pipeline and a smoke-test grid. Today it is a flashable image with the lights on. Live TV from an antenna, FM and AM radio from a USB dongle, AirPlay mirroring from your phone, DVDs ripping into a real library with cover art, YouTube on the big screen, and a header full of rig telemetry that updates while you watch. One flash to the NVMe and the rig has an entertainment center.

Playbill home screen on a TV, showing three horizontal rows: Continue Watching with three poster tiles and progress bars, Your Apps with YouTube, Cast, Trails Nearby, and Music launchers, and Offline Library — Movies with five poster tiles and a See all tile. Top-right shows live rig telemetry.
Playbill v0.1 home. Three rows: where you left off, what you can launch, and what is on the local drive. The top-right strip is live rig telemetry pulled from Headwaters: state of charge, solar in, cabin temperature, and the clock.

What "an image" actually means here

The Playbill repo builds a single artifact: trailcurrent-playbill-q6a-v0.1.0.img. It is a complete rootfs targeted at the Radxa Dragon Q6A, with the patched embloader, the Plymouth boot splash, the TrailCurrent-branded Ubuntu Noble desktop, the Playbill app, and every kernel module the hardware needs already inside. Run ./image/build.sh if you want to roll your own. Hold the EDL button, run ./image/flash.sh --os <image>, and a few minutes later the Q6A boots into Playbill.

The next step is the one a lot of people care about. We are going to publish the same .img as a download so you do not need a build host, edl-ng, or any of the Qualcomm toolchain to put Playbill on a board. Flash it the way you flash a Raspberry Pi image. The pipeline is reproducible, the artifact is byte-identical to ours, and the only difference between "build it yourself" and "download it" is the half hour of dependencies you skip.

Live TV from a USB antenna tuner

The Live TV tab drives a Hauppauge WinTV-dualHD. Two ATSC tuners on one USB stick, plug it in, click Rescan, and the app walks every UHF and VHF physical channel in your area looking for broadcast multiplexes. When the scan finishes, the channel tile grid shows what it found. Click a tile and mpv comes up fullscreen with hardware-decoded 1080i over-the-air TV, switched in well under a second on the Q6A's Adreno 643.

Playbill Live TV channel grid showing ten ATSC virtual channels with call signs WCBS-DT, WNBC-DT, WNYW-DT, WABC-DT, WWOR-DT, WPIX-DT, WNET-DT, WPXN-DT, WNJU-DT, and WXTV-DT, with channel 4.1 highlighted
After a scan, every detected ATSC virtual channel becomes a tile. Two tuners means two simultaneous streams, which matters the moment you want to record one channel while you watch another.

The wrinkle worth surfacing: Radxa's BSP kernel ships zero USB DVB drivers. The whole em28xx family, the LGDT3306A demodulator, the Si2157 tuner, the EEPROM helper, all gone. We ship them ourselves as trailcurrent-playbill-dkms, a DKMS sibling package that rebuilds against whatever kernel is installed. The main trailcurrent-playbill deb depends on it. apt handles dependency resolution and DKMS handles rebuilds on kernel updates, the same pattern nvidia-driver uses on x86. You never see it. You install Playbill, the tuner works.

The scan itself is still finicky in some signal environments. That is the open punch-list item for the v0.1 image. Strong-signal urban antennas walk the channel plan in about a minute. Marginal-signal scans sometimes miss multiplexes and need a second pass. We will keep tuning the dvbv5 frontend until it is boring.

Radio that ships with the rig

The Radio tab drives an RTL-SDR USB dongle: FM and AM, a tunable dial, ten preset slots, and a scanner that sweeps a band looking for signal. Tune by tapping the dial, save a station by pressing Enter on an empty preset, switch bands with the B key. It is intentionally radio-like. There is no station name database to be wrong about, no Spotify graph to lean on. Just a frequency, a dial, and the audio coming out of the cabin speakers.

Playbill Radio tab showing the FM band selected, a 101.5 MHz dial readout, a horizontal frequency scale with a tuning marker, and ten preset slots saved with FM and AM frequencies
Tuned to 101.5 FM. Presets persist on the NVMe, so the next time you fire up Playbill at the same campground you are one button-press away from the local station.

Under the hood the kernel's built-in dvb_usb_rtl28xxu driver is blacklisted in the image so userspace librtlsdr can claim the device. That is the kind of decision you only get to make if you own the image. A general-purpose distro cannot guess whether you want the DVB driver or the SDR driver on the same chip.

The big screen for your latest trip

Playbill has a Cast tab that announces itself as an AirPlay receiver on the local network. Open the Control Center on an iPhone or iPad, tap Screen Mirroring, pick the Playbill, and whatever is on your phone is on the TV. Software H.264 decode hits a fullscreen Wayland surface. The use case it really earns its keep on: the photos and video you just shot.

You pull into camp. The afternoon hike turned into one of those days, you came back with a phone full of pictures and a couple of clips, and the cabin fills up with whoever you are traveling with. Cast from the phone, the whole album is suddenly on a screen everyone can see at once instead of being passed around. Same thing for the GoPro you offloaded to your phone, the kid's drawing video, the campfire panorama, the bear you actually saw. The phone you took it all on is the easiest place to drive the slideshow from, and Playbill is the receiver.

DVDs become a library you actually use

Insert a DVD. A desktop notification slides in. Click Rip and Playbill copies the disc to ~/Videos/Playbill Library/Movies/<Title>/, looks up the title against OMDb, and writes a .json sidecar with the poster, year, director, runtime, and synopsis. The Library tab picks it up on the next scan and the movie appears in the Movies grid with cover art. The disc is shelved. The shelf is gone.

Playbill Offline Library tab populated with fourteen movie posters arranged in a seven-column grid, with Movies (14) and TV Shows (0) filter chips at the top and an "892.4 GB free of 1.0 TB" disk-space line beneath the heading
Offline Library after a stack of DVD rips. The chip counts come straight from a periodic scan of the on-device library directories, and free space is read from the live NVMe mountpoint, no mock numbers.

The library lives on Playbill's NVMe. That is the storage split we drew on day one: Headwaters keeps its smaller drive for map tiles and the Docker stack, and Playbill carries the bigger drive because media is heavy. Movies and TV Shows live in the Offline Library tab. Music has its own top-level tab next door, because the metadata, the play mode, and the detail UI all diverge from video the way Apple TV, Plex, and Kodi all split them. Inserting an audio CD triggers a parallel flow: rip, tag, file under Music. Inserting a DVD triggers the OMDb lookup and a poster in Library. Whichever way the media arrives, it lands somewhere obvious.

YouTube as a real app

Apps tab, click YouTube, and a chromed web view comes up with the same arrow-key navigation as the rest of the app. The remote text input streams characters into the YouTube search box and results land in a 10-foot-friendly list. It is not a fork of the YouTube app and it is not a scraper. It is the standard web client wrapped tightly enough that a phone, a keyboard, or a future IR remote can drive it without ever touching a mouse.

The rig in the corner of your eye

Look at the top-right of any Playbill screenshot. Battery state of charge. Current solar in. Cabin temperature. Clock. That strip is not a placeholder. It subscribes to the same MQTT topics Milepost and Overlook do, and the values update while the movie is playing. The Rig tab takes the same feed and turns it into a full readout: GNSS location, an energy gauge with state-of-charge plus solar in, consumption, voltage and time remaining, fresh / grey / black tank levels, climate with humidity and air quality, and a row of named lights you can flip from the couch.

Playbill Rig tab showing a Location tile with latitude, longitude, elevation and GNSS Locked status; an Energy tile with a circular state-of-charge gauge at 87 percent and stats for solar in, consumption, and voltage; a Water tile with three animated tank meters (fresh, grey, black); a Climate and Air tile with 68 degrees Fahrenheit, humidity, TVOC and eCO2; and a Lights tile with eight named light buttons, four of them on
Rig tab. Same data Milepost shows on the wall and Overlook shows on your phone, only sized for the couch. The light tiles toggle real switches over MQTT, so tapping Ceiling from the TV is the same event a wall button would have fired.

The light row is worth a moment. The names and icons come from whatever the user configured in the Headwaters PWA. Rename Galley to "Kitchen" there and it renames here on the next retained-config publish. Toggling never patches local state optimistically either. Playbill sends the command and waits for the device's own status broadcast to update the visible on/off. That sounds picky until you realize it is the only way a wall panel, a phone, a CAN button, and the TV can all stay in agreement when they are all trying to drive the same fixture.

The clock at the top is worth a line too. Playbill does not run NTP. Headwaters does, and Playbill asks Headwaters for the time over the local network on boot. That means the rig has a correct clock the moment Headwaters does, with no internet round-trip, and stale boards parked all winter wake up with the right time the moment they see the gateway.

The small things that add up

A lot of the work between the last post and this one is not headlining a section. It still shows up the moment you live with the box:

  • Audio leveling across sources. Live TV is loud. Old DVDs are quiet. Radio is somewhere in between. Switching sources used to mean a jump scare for whoever is in the cabin. Now Playbill normalizes loudness across sources so the master volume means the same thing whether you came from FM or a Blu-ray rip.
  • Modal handling on the remote. The phone remote, keyboard, and the IR remote we are bringing up all share one navigation model now, including modal dialogs. Hit Back inside a "Rip this DVD?" prompt and you cancel the prompt, not navigate out of the Library tab behind it.
  • Settings is honest. The Settings page in v0.1 collects exactly the fields Playbill needs to claim itself to Headwaters: a Headwaters hostname, a username, a password, and a one-click "Save and Connect" with validation. The system-wide TLS trust store is updated at the same time so OS-level browsers stop yelling about the rig's certificate.
  • An on-screen keyboard. When a field has focus and no physical keyboard is attached, an OSB pops up and the D-pad walks it. The phone-remote text streaming we shipped last post still works; the OSB is the offline equivalent.

What still needs work

Calling this v0.1 instead of "first working image" is deliberate. The image boots, the features all come up, and the rig is usable. But the build is honest about what is wobbly:

  • The ATSC scan is finicky on weaker signal. We have a rescan, but you may need it.
  • Snap is not installed in the image on purpose, which means anything that ships as a snap on Ubuntu (cough Firefox) needs the deb path instead. The image already routes around the Firefox case; other snap-only apps you install yourself will need the same treatment.
  • Netflix and other DRM clients are not first-class yet. Mirror from your phone for now.
  • The IR remote is bench-tested, not finished. The same protocol the phone remote uses is on the CAN bus already, so the IR work is a sensor-driver problem, not a UI problem.
  • A few rough edges in transitions and focus that will go away post-flash.

Where to find it

The repo is TrailCurrentPlaybill. The operator guide is in docs/SETUP.md and the source for everything you see in the screenshots above is in app/, controller/, and image/. If you have a Radxa Dragon Q6A on the bench, you can have Playbill running on it today. If you would rather wait for the prebuilt .img, that drops next, and the moment it does it will be linked from the Getting Started page on this site.

The next post on Playbill will be the day the prebuilt image is up. Same flash flow as a Raspberry Pi, no Qualcomm toolchain in the picture, no dev environment to install. Plug in HDMI, plug in power, and the rig has a TV.