MakeThingsWork.dev

The Very First Thing I Built

The year was 2011.

I was on my 5th year of college working on my Bachelors in Communication1. I worked at the college radio station doing imaging and audio production and loved every second of my time there. One of the most common questions we got from our listeners, both over the phone and via our request line email, was "What song is/was playing?!"

As a non-commercial station run by students and just a couple of faculty, there were never the resources for a website that provided useful information about what was playing. Our radio automation software at the time was fairly limited in what it could do and even if we had a site there wasn't a straight path to getting a "now playing" feature to our listeners.

This is the story of how I built the solution.

The Background

At the time I was completely fresh to the world of programming. Heck, I didn't even have a strong opinion on what browser I used. I did have a radio show at the station with a good friend of mind where we did a bunch of semi-funny comedy sketches. The year prior, I'd wanted to create a website for our show where I could upload our sketches and some videos as a companion platform to our show... but I had no clue how to do that.

Fortunately, my dad had been experimenting with Joomla! at his company for internal usage. He shared his experience with me and I'd stood up a website on Bluehost2 with trial and error. I was so clueless about setting up DNS that even with the very simple instructions I had to ask a poor support agent a bunch of questions to get some free advice but I got there in the end. I just used out-of-the-box Joomla! modules and plugins and hacked through some CSS files. The site worked, was ugly, and hosted all our audio and video. Success!

This was the extent of my website experience when my last semester of college rolled around at the beginning of 2011.

The Idea

To graduate you had to take Capstone and come up with some big project, get it sponsored by faculty, plan it, design it, execute it, and then present on it at the end of the semester. Most of my fellow seniors were making media-related projects that raised awareness for noble causes or creating original content. I was completely lost 3.

I had thoroughly enjoyed setting up the site for my radio show and one day at the station, after answering yet another call from a listener wanting to know what was playing, a little light bulb went off: I'll make a website with Joomla! that will show what's playing!!!

But wait - that's not really a communications project. Getting that sponsored seemed unlikely except for one thing: the station manager was also my advisor. Selling the idea to her wasn't too difficult and when I framed it in the context of "communications students really need to develop 'web skills'" 4 everyone was on board.

Cool, I had my Capstone project. Now I just had to build it. Oh, the confidence of the person at the very start of the Dunning-Kruger is a powerful thing.

The Log Parser

I started with the crux of the project which was extracting now playing data from the radio automation software. With backing on the project I was given access to the on-air Windows PC where the software was running. After doing a lot of digging I discovered a plain text file that the application was writing to regularly. Essentially it was storing all of the text from the UI (which changed as songs played) in a simple text file. Since the software itself had no export capability, I felt like this file was the key, but it was full of all kinds of unneeded garbage and was clearly never intended to be used by anyone.

The downside to the useful data in the file was that the UI truncated song and artist names and this truncation persisted to this temp file, but honestly that would be better than nothing and after some discussion with the operations manager we decided that was probably the best we were going to get.

This post will contain some of the first code I ever wrote, but the very first thing I wrote was a script using Microsoft's logparser. Sadly this script is lost to time. I've dug through every backup I have but couldn't locate the script. All I could find was a flowchart of the whole process that includes some details on what the script did. Flowchart

I created a scheduled task that regularly copied the temp file from the automation software into a working directory and added .txt extension.

I then, due to not knowing how else to do it, parsed this file with logparser for lines that contained a certain category code. These were codes that represented songs. A separate file for each code was created and then the relevant lines were added to those files. Again, this was because I had no clue what I was doing and was using very very simple querying of the file. Then, I would re-combine those into a single file, sorted by the provided timestamp in the file. This essentially gave me a regularly updated "clean" file that contained truncated (but sorted!) song and artist names.

Nice, now we had a workable file that was updated in near real-time with all the needed song and artist data! Now how was I going to get it to a website?

MagicRDS

Writing this out today is so funny. I could write a single Ruby script to handle all of this but back then I had no idea.

I needed to get the data from the most recent line in my new file from the automation computer to the website. A simple POST request would've done the trick but I didn't know what that was. My Google-fu was strong, however, and I discovered a program called MagicRDS that allowed you to send data from a local text file and broadcast it via RDS (Radio Data System) 5. It also had the option to send it via HTTP! So I had a windows app reading a text file and sending a GET request. magic_rds In the screenshot you can see that you select a local file. I then used the "Cut characters from beginning" and "Cut characters from end" to slice out the part of the line I wanted.

I remember at the time I couldn't figure out how to reliably split the artist and song title on the server side. I wasn't familiar with scripting languages so I simply ran two instances of MagicRDS. One instance plucked out the artist and one plucked out the song title and sent this to two different .php files on my server. My Googling had discovered a sample script in ASP that would take data from a GET request and save it to a file, and I asked a friend from church who was smarter than me to convert it to PHP.

<?php
// songtitle.php
$stream=$_GET["song"];
$filename="songtitle.txt";
if ($stream!=""){
	$textfile=fopen($DOCUMENT_ROOT.$filename,"w");
	fwrite($textfile,$stream."");
	fclose($textfile);
	$textfile=null;
} else {
	if ((file_exists($DOCUMENT_ROOT.$filename))==true){
		$textfile=fopen($DOCUMENT_ROOT.$filename,"r");
		print("On air: ".fgets($textfile,100));
		fclose($textfile);
		$textfile=null;
	}
}
?>

Beautiful, right? There was another nearly identical that handled the artist.

So at this point I had a script parsing the log data out of the temp file, putting it into a clean file, and two instances of a program sending a GET request to my site that was writing that data to some .txt files.

The songs were on the server, I repeat, the songs were on the server!

Now how do I display this?

Flash, Of Course!

I wanted it to be flashy, modern, beautiful, and dynamic. What's a complete noob to web dev to do? Well, Flash of course!

This was the very second bit of code I ever wrote. I built a flash file and wrote some action script that would read data from the text files. Luckily for you, dear reader, I did manage to find the original .swf file and decode it so I could extract the ActionScript!

In all its glory:

package
{
   import flash.display.MovieClip;
   import flash.events.Event;
   import flash.net.URLLoader;
   import flash.net.URLRequest;
   import flash.text.TextField;
   
   public class Main extends MovieClip
   {
      
      public var artist:TextField;
      
      public var song:TextField;
      
      internal var textLoader:URLLoader = new URLLoader();
      
      internal var SongtextLoader:URLLoader = new URLLoader();
      
      public function Main()
      {
         super();
         this.textLoader.addEventListener(Event.COMPLETE,this.textLoaded);
         this.textLoader.load(new URLRequest("artist.txt?" + Math.random()));
      }
      
      internal function textLoaded(param1:Event) : void
      {
         this.artist.text = param1.target.data;
         this.SongtextLoader.addEventListener(Event.COMPLETE,this.SongtextLoaded);
         this.SongtextLoader.load(new URLRequest("songtitle.txt?" + Math.random()));
      }
      
      internal function SongtextLoaded(param1:Event) : void
      {
         this.song.text = this.SongtextLoader.data;
         this.textLoader.addEventListener(Event.COMPLETE,this.textLoaded);
         this.textLoader.load(new URLRequest("artist.txt?" + Math.random()));
      }
   }
}

Look at that! I'd clearly read about caching and knew to add Math.random() to the file paths. Those were the early signs of greatness! For this post I managed to get the file to run with Ruffle so you can see what it looked like back then: Now Playing Sample

And with that I'd managed to get the current song and artist from the radio automation software to display on a website. It was a crazy and convoluted process but it worked!

Putting It Together

After that I spent hours hammering together a Joomla! site that displayed all of the station's information with places for students to write music reviews and a place for people to listen to the live stream. But at the very center was my "Now Playing" widget and people couldn't have been happier.

This isn't the earliest iteration of the site but as of writing you can see a very early version of my masterpiece on the WaybackMachine.

What's The Story Today

I still maintain that college radio website. Over the years they upgraded their radio automation software and now dump data to Dropbox. I built a standalone Rails API app that simply ingests this file and saves it in a database and provides endpoints for searching and paging through the logs. This is used by the current site to pull things in and if the site ever changes this app will work the same,

I'm very proud of that time because it was 100% about figuring it out and getting across the finish line with what little knowledge I had. Was it good? No. Was it stable? Heck no. But it worked and I was able to solve a long-standing problem that made our listeners very happy.

And that's how you make things work.

Thanks for reading!

-- Rick


  1. I didn't spend 5 years trying to get a Communications degree, there was a progression: Electrical Engineering -> Marketing -> Communications. Long story...

  2. Shared hosting is a nightmare. I didn't know that at the time - it was just cheap. Anyone still use a cPanel??

  3. Lost? The guy who spent 5 years in college to get a communications degree was lost? Shocking.

  4. "Web Skills" was a phrase my professors used a lot. I'm not sure they knew specifically what they meant but I used it to my own advantage in this case.

  5. RDS is what allows your radio in your car to display the name of the station, the song, and artist. If anyone listens to terrestrial radio anymore.

#actionscript #flash #learning #oldschool #php