Where to even start with this one, it's a long story.

It all begins with... well, it all begins in the summer after I graduated 5th grade, and for my birthday, my dad bought me a brand-new RadioShack TrunkTracker. It was the state-of-the-art and can pick up frequencies from 40MHz to 900MHz (with lots of gaps, because, regulations or something). I had a blast with it, and every family vacation I would take it, along with frequency manuals, diligently programming it by hand, and pick up various agencies from Cleveland to Myrtle Beach.

Of course, in the decades since then, new digital systems are in place and being used. Most agencies in my area switched to digital trunk systems, specifically the MARCS P25 state-wide system.

For a while, I have been toying with SDR's. My first was a cheap Terratec, my latest is nothing to brag about, an RTL-SDR v3. And also in the meanwhile, I picked up my amateur general license, but that's a topic for another post.

Back to the technical problem at hand:

I have a receiver, I can decode P25 audio on a computer. I would like to stream via internet for personal, internet connected listening (and with an eye on providing the service to the public via broadcastify).

Problem 1: Boatbod's release of OP25 doesn't support my Linux distribution. This has been solved.

Problem 2: Connecting a local audio source to a recording sink without interfering with other local audio.

This is part of a bigger problem, of which I noticed there is no user-friendly solution, and it works something like this: I need to be able to create "dummy" audio output devices in pulseaudio, which will act as input devices to other programs. These new input devices need to look like ALSA sources to some programs. Using pulseaudio's built in monitor sinks is not an option: that requires using a dedicated sound card cranked to 100% per application. I'm not using a dedicated device, that isn't an option. Also, it's just darned neat to be able to mix and match audio (for that matter video -- but that's a separate topic concerned with obs-v4lsink). So, a virtual plugboard for linux that can hook up to remote sinks, and then have those remote sinks broadcast.

Enter icecast.

Icecast will handle the heavy lifting on the public-facing server. Getting that working is easy enough. Follow the documentation, but be very careful that the URL used to connect to the web admin interface is the same as the one in the config, or you'll have problems with failed authentication. (This is a portent of things to come -- it seems like the people who program this audio software are content with leaving users with vague and completely useless error messages.)

Great, so the admin interface works (note to self: markdown for images, stop using hugo) image-int

Now, I have to feed icecast a stream. This shouldn't be too hard. Just use that liquidsoap that op25 talks about!

nope sorry liquidsoap is terrible to use

I'll just follow their well-written and seemingly useful documentation, says the naive user. Sure, just play a playlist locally!

Well making a playlist shouldn't be hard. Let's just grab some files and put them in. Since the wonderful documentation says to start with ogg, that's fine Since I just know there will be format errors later, I'll make some test directories.

cd /media/music; find . -type f > index.txt
for x in wav ogg mp3; do
  egrep "*.${x}$" index.txt > $x.pls

that should be fine. even if the playlists are huge or tiny.

Great let's see how well liquidsoap works!


liquidsoap 'out(playlist("mp3.pls"))'                                                                                                                                                                [1:01:4
At line 1, char 0-4:
Error 4: Undefined variable out

Great. Well maybe they meant output‽


liquidsoap 'output(playlist("mp3.pls"))'                                                                                                                                                             [1:03:46]
At line 1, char 7-16:
Error 5: this value has type
but it should be a subtype of
  (_) -> _

OF COURSE it should be a subtype of (_) -> _

At this point I am nearly giving up on liquidsoap. The problem isn't the audio files.

If I can't get it outputting locally on my machine without spewing ridiculous cryptic error messages, how am I supposed to get this working for a source for a public facing broadcast server‽

I would go to darkice at this point, but I guess I'll just read deeper into liquidsoap and just FORCE it to work.