Before moving to WordPress from BlogEngineDotNet I had a widget that made a call to a specially created Icecast XSL file to display the current playing track title in a Widget. This worked great, but it was static and wouldn’t update if the track changed. Migrating to WordPress, I wanted to achieve the same track playing information but up the game with it updating to display new track information. The latest Icecast server has built in metadata report in JSON format now so I wanted to use this over parsing an XSL file. This took me roughly about a day and a half to complete, mostly due to nearly all examples of parsing JSON with Javascript do not work and I know little Javascript. Here is an overview of the process invovled.
- Configure Icecast headers and SSL certificates
- Insert Javascript in headers.php
- Insert HTML in Widget for display
Configure Icecast
You can skip this part if you are not using SSL. Also note Apache and Icecast are running on the same server. Since my site defaults to SSL (https) I have to configure Icecast for SSL.
The first step is to create the proper SSL certificate file format that Icecast uses. It requires a Public/Private keypair file. I used my Let’s Encrypt certificates and concatenated them together into one file.
cd /usr/share/icecast cat /etc/letsencrypt/live/autonarcosis.com/cert.pem > icecast.pem cat /etc/letsencrypt/live/autonarcosis.com/privkey.pem >> icecast.pem chown icecast.icecast icecast.pem chmod go-r icecast.pem
Now to edit the /etc/icecast.xml configuration file to enable an SSL port and point to the icecast.pem file. Create a second listen-socket container with a different port and enable SSL. Insert http-headers container before paths container for access control (this gives permission for the javascript to access the JSON data). Put the ssl-certificate path setting within the existing paths container.
<listen-socket> <port>8002</port> <ssl>1</ssl> </listen-socket> <http-headers> <header name="Access-Control-Allow-Origin" value="*" /> </http-headers> <paths> <ssl-certificate>/usr/share/icecast/icecast.pem</ssl-certificate> </paths
Save the icecast.xml file. Enable the new port in the firewall.
firewall-cmd --permanent --add-port=8002/tcp firewall-cmd --reload
Restart Icecast, which will now be listening on an SSL port.
systemctl restart icecast.service
You can view Icecast error log file /var/log/icecast/error.log to see if the SSL certificate loaded properly. You should see something similar to this.
[2016-03-11 15:41:45] INFO connection/get_ssl_certificate SSL certificate found at /usr/share/icecast/icecast.pem [2016-03-11 15:41:45] INFO connection/get_ssl_certificate SSL using ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA2 56:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-R SA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SH A384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA25 6:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-S HA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-S HA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
Configure WordPress
Now it is time to configure WordPress. Below is the Javascript that I hacked together to pull the Icecast metadata from the data feed in JSON format. This is WordPress modified Javascript and will not work outside WordPress. Place this Javascript in the HEAD section of your themes headers.php.
<script type="text/javascript"> function radioTitle() { jQuery.ajax({ url: "https://www.autonarcosis.com:8002/status-json.xsl", //force to handle it as text dataType: "text", async: true, success: function(data) { //data downloaded so we call parseJSON function //and pass downloaded data var json = jQuery.parseJSON(data); //now json variable contains data in json format //let's display a few items // this is the element we're updating that will hold the track title jQuery('#track-title').text(json.icestats.source.title); // this is the element we're updating that will hold the listeners count jQuery('#listeners').text(json.icestats.source.listeners); } }); }; jQuery(document).ready(function(){ setTimeout(function(){radioTitle();}, 2000); // we're going to update our html elements / player every 15 seconds setInterval(function(){radioTitle();}, 15000); }); </script>
Add the HTML to the widget so the information will be displayed.
<p> </br> Listeners: <span id="listeners">00</span></br> Current track: <span id="track-title">LIVE</span> </p>
That’s all there is to it. There could possibly be a better way or function to do this.
I used this blog entry as a base for figuring this out; https://linge-ma.ws/update-listeners-track-on-a-website-using-icecast-jsonp-and-jquery/