• Reading time:16 mins read
Stream Radio Script

Stream Radio Script

Today I have prepared another really great tutorial for you. Recently I have started development of my own radio software (as module for Dolphin CMS) and got interesting results. So, I would like to share you with some results about it. It will be nice looking (CSS3) radio script. It consists from three main elements: header (with nice animated search bar and integrated radio player), left side (with list of categories and subcategories) and right side (which will contains list of recent/ or filtered stations).

Here are our demo and downloadable package:

Live Demo

[sociallocker]

download in package

[/sociallocker]


Ok, download our source files and lets start coding !


Step 1. HTML Markup

This is markup of the one of used template files. This is template of our main (index) page. Here it is:

templates/main_page.html

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <title>Stream Radio Script | Dev School</title>
        <link href="css/main.css" rel="stylesheet" type="text/css" />
        <link href="css/radio.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
        <script>
            google.load("jquery", "1.7.1");
        </script>
        <script src="js/script.js"></script>
    </head>
    <body>
        <header>
            <h2>Stream Radio Script</h2>
            <a href="https://dev-school.net/stream-radio-script/" class="stuts">Back to original tutorial on <span>Dev School</span></a>
        </header>
        <div class="container">

            <form method="get" class="header" action="javascript:void(0)" onsubmit="get_stations_by_keyword(); return false;">
                <input type="text" id="search" value="Search" name="s">
                <span>
                    <div id="rplayer">
                        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="191" height="46" bgcolor="#FFFFFF">
                        <param name="movie" value="player/ffmp3-config.swf" />
                        <param name="flashvars" value="url=http://scfire-dtc-aa04.stream.aol.com:80/stream/1013/&lang=en&codec=mp3&volume=100&introurl=media/welcome.mp3&autoplay=true&traking=false&jsevents=false&buffering=5&skin=player/def/skin.xml&title=SKY.FM 80s" />
                        <param name="wmode" value="opaque" />
                        <param name="allowscriptaccess" value="always" />
                        <param name="scale" value="noscale" />
                        <embed src="player/ffmp3-config.swf" flashvars="url=http://scfire-dtc-aa04.stream.aol.com:80/stream/1013/&lang=en&codec=mp3&volume=100&introurl=media/welcome.mp3&autoplay=true&traking=false&jsevents=false&buffering=5&skin=player/def/skin.xml&title=SKY.FM 80s" width="191" scale="noscale" height="46" wmode="opaque" bgcolor="#FFFFFF" allowscriptaccess="always" type="application/x-shockwave-flash" />
                        </object>
                    </div>
                </span>
            </form>
            <div class="clear"></div>
            <div class="genres_par">
                <ul class="genres">
                    <li id="1" val="Alternative"><a href="javascript:void(0)">Alternative</a>
                        <ul>
                            <li id="11" val="Classic+Alternative"><a href="javascript:void(0)">Classic Alternative</a></li>
                            <li id="12" val="Industrial"><a href="javascript:void(0)">Industrial</a></li>
                            <li id="13" val="New+Wave"><a href="javascript:void(0)">New Wave</a></li>
                            <li id="14" val="Punk"><a href="javascript:void(0)">Punk</a></li>
                        </ul>
                    </li>
                    <li id="2" val="Classical"><a href="javascript:void(0)">Classical</a>
                        <ul>
                            <li id="21" val="Modern"><a href="javascript:void(0)">Modern</a></li>
                            <li id="22" val="Opera"><a href="javascript:void(0)">Opera</a></li>
                            <li id="23" val="Piano"><a href="javascript:void(0)">Piano</a></li>
                            <li id="24" val="Romantic"><a href="javascript:void(0)">Romantic</a></li>
                            <li id="25" val="Symphony"><a href="javascript:void(0)">Symphony</a></li>
                        </ul>
                    </li>
                    <li id="3" val="Electronic"><a href="javascript:void(0)">Electronic</a>
                        <ul>
                            <li id="31" val="Breakbeat"><a href="javascript:void(0)">Breakbeat</a></li>
                            <li id="32" val="Dance"><a href="javascript:void(0)">Dance</a></li>
                            <li id="33" val="Electro"><a href="javascript:void(0)">Electro</a></li>
                            <li id="34" val="House"><a href="javascript:void(0)">House</a></li>
                            <li id="35" val="Techno"><a href="javascript:void(0)">Techno</a></li>
                            <li id="36" val="Trance"><a href="javascript:void(0)">Trance</a></li>
                        </ul>
                    </li>
                    <li id="4" val="Metal"><a href="javascript:void(0)">Metal</a>
                        <ul>
                            <li id="41" val="Classic+Metal"><a href="javascript:void(0)">Classic Metal</a></li>
                            <li id="42" val="Heavy+Metal"><a href="javascript:void(0)">Heavy Metal</a></li>
                            <li id="43" val="Metalcore"><a href="javascript:void(0)">Metalcore</a></li>
                            <li id="44" val="Power+Metal"><a href="javascript:void(0)">Power Metal</a></li>
                        </ul>
                    </li>
                    <li id="5" val="Pop"><a href="javascript:void(0)">Pop</a>
                        <ul>
                            <li id="51" val="Dance+Pop"><a href="javascript:void(0)">Dance Pop</a></li>
                            <li id="52" val="Oldies"><a href="javascript:void(0)">Oldies</a></li>
                            <li id="53" val="Top+40"><a href="javascript:void(0)">Top 40</a></li>
                            <li id="54" val="World+Pop"><a href="javascript:void(0)">World Pop</a></li>
                        </ul>
                    </li>
                </ul>
                <div class="clear"></div>
            </div>
            <div class="stlist">__stations__</div>
            <div class="clear"></div>
            <div class="cred">Powered by <a href="https://dev-school.net/">Dev School</a></div>

        </div>
    </body>
</html>

First – pay attention how script loads jquery library from google. This can be pretty useful if you don’t like to keep this file directly at your host. Our header element contain nice search bar with embedded jasl player. I have used great FFMp3 Live Stream Player for our result. You can read about this player here: http://ffmp3.sourceforge.net/. It allows us play audio streams without any problems. Next – at left side (under the header) we have UL-LI based list of categories (with subcategories). And right side will contain list of last stations and, when we search or select category – right side will be filtered Ajaxy. For now – it cantain __stations__ key (template key) which we will replace to actual value with PHP. Our next template file – template of our radio player:

templates/radio.html

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="191" height="46" bgcolor="#FFFFFF">
<param name="movie" value="player/ffmp3-config.swf" />
<param name="flashvars" value="url=__stream__&lang=en&codec=mp3&volume=100&introurl=&autoplay=true&traking=false&jsevents=false&buffering=5&skin=player/def/skin.xml&title=__title__" />
<param name="wmode" value="opaque" />
<param name="allowscriptaccess" value="always" />
<param name="scale" value="noscale" />
<embed src="player/ffmp3-config.swf" flashvars="url=__stream__&lang=en&codec=mp3&volume=100&introurl=&autoplay=true&traking=false&jsevents=false&buffering=5&skin=player/def/skin.xml&title=__title__" width="191" scale="noscale" height="46" wmode="opaque" bgcolor="#FFFFFF" allowscriptaccess="always" type="application/x-shockwave-flash" />
</object>

Of course, it contains own template keys (__title__ and __stream__) which we will use after.

Step 2. CSS

Here are our stylesheets files:

css/main.css

First one just contains styles of our test page (this file always available in our package)

css/radio.css

/* header area */
.header {
    height:62px;
}
.header input {
    background:#aaa url(../images/search.png) no-repeat 5px center;
    border:1px solid #888;
    border-radius:10px;
    float:right;
    margin:14px 10px 0 0;
    outline:none;
    padding-left:20px;
    width:200px;

    -webkit-transition: 0.5s;
    -moz-transition: 0.5s;
    -o-transition: 0.5s;
    transition: 0.5s;
}
.header input:focus {
    background-color:#eee;
    width:300px;
}
.header > span {
    display:block;
    float:left;
    line-height:40px;
    padding:7px;

    -webkit-transition: 0.5s;
    -moz-transition: 0.5s;
    -o-transition: 0.5s;
    transition: 0.5s;
}

/* stations list */
.stlist {
    float:right;
    margin-right:1%;
    width:71%;
}
.stlist ul {
    list-style:none outside none;
    margin:0;
    padding:0;
}
.stlist ul li {
    border-bottom:1px dotted #444;
    overflow:hidden;
    padding:10px;
}
.stlist ul li > a > img {
    border:1px solid #CCC;
    float:left;
    height:85px;
    margin-right:15px;
    padding:1px;
    width:85px;
}
.stlist ul li > div {
    float:right;
    margin-left:15px;
    margin-top:-5px;
}
.stlist ul li > p.label,.stlist ul li > p.track {
    font-size:11px;
    font-weight:700;
}
.stlist ul li > p.label {
    color:#888;
}
.stlist ul li > p.channel {
    font-size:14px;
    font-weight:700;
    margin-bottom:17px;
}

/* genres list */
.genres_par {
    border-right:1px solid #ccc;
    float:left;
    width:26%;
}
ul.genres,ul.genres ul {
    list-style-type:none;
    margin:0;
    padding:0;
}
ul.genres ul {
    display:none;
    overflow:hidden;
    padding:0 15px;
}
ul.genres ul li {
    margin:3px;
}
ul.genres a {
    color:#333;
    display:block;
    font-size:18px;
    padding:4px 0;
    text-align:center;
    text-decoration:none;
}
ul.genres ul a {
    font-size:12px;
    text-align:left;
}
ul.genres li {
    border-bottom:1px solid #CCC;
    margin:0;
}
ul.genres li ul li a {
    background:none repeat scroll 0 0 #5bb951;
    border-radius:2px;
    color:#FFF;
    font-size:12px;
    padding:6px;
}
ul.genres li ul li a:hover {
    background-color:#53854E;
}

Step 3. JS

js/script.js

$(document).ready(function(){
    $('#search').blur(function() {
        if ('' == $('#search').val()) $('#search').val('Search');
    });
    $('#search').focus(function() {
        if ('Search' == $('#search').val()) $('#search').val('');
    });

    $('ul.genres li a').click( // category slider
        function() {
            var checkElement = $(this).next();
            if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
                $('.genres li ul').slideUp(150);
                $(this).next().slideToggle(150);
            }
        }
    );

    $('ul.genres ul li a').click( // get stations by category
        function() {
            $.ajax({ 
                type: 'GET', 
                url: 'index.php', 
                data: 'action=get_genre_stations&id=' + $(this).parent().attr('id') + '&name=' + $(this).parent().attr('val'),
                success: function(data){ 
                    $('.stlist').fadeOut(400, function () { 
                        $('.stlist').html(data);
                        $('.stlist').fadeIn(400); 
                    });
                } 
            });
        }
    );
});
function play(id) { // play function
    $('#rplayer').load('index.php?action=play&id=' + id, function() {});
    return false;
}
function get_stations_by_keyword() { // get stations by keyword
    var keyword = $('#search').val().replace(/ /g,"+");
    $.ajax({ 
        type: 'GET', 
        url: 'index.php',
        data: 'action=get_keyword_stations&key=' + keyword,
        success: function(data){ 
            $('.stlist').fadeOut(400, function () { 
                $('.stlist').html(data);
                $('.stlist').fadeIn(400); 
            });
        } 
    });
}

As you see – nothing is difficult there. Just several event handlers, and two new functions (to play radio station and so search for stations by keyword).

Step 4. PHP

index.php

<?php

// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);

$aStations = array(
    0 => array(
        'category' => 31,
        'name' => 'EuroDance',
        'desc' => 'The newest and best of Eurodance hits',
        'url' => 'http://www.di.fm/eurodance',
        'br' => 96,
        'stream' => 'http://scfire-mtc-aa06.stream.aol.com:80/stream/1024'
    ),
    1 => array (
        'category' => 34,
        'name' => 'House',
        'desc' => 'Silky sexy deep house music direct from New York city!',
        'url' => 'http://www.di.fm/house',
        'br' => 96,
        'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1007'
    ),
    2 => array (
        'category' => 13,
        'name' => 'Trance',
        'desc' => 'The hottest, freshest trance music from around the globe!',
        'url' => 'http://www.di.fm/trance',
        'br' => 96,
        'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1003'
    ),
    3 => array (
        'category' => 51,
        'name' => 'Electro House',
        'desc' => 'An eclectic mix of electro and dirty house',
        'url' => 'http://www.di.fm/electro',
        'br' => 96,
        'stream' => 'http://scfire-ntc-aa04.stream.aol.com:80/stream/1025'
    )
);

function searchByCat($iCat, $aStations) {
    $aRes = array();
    foreach ($aStations as $i => $aInfo) {
        if ($aInfo['category'] == $iCat) {
            $aRes[$i] = $aInfo;
        }
    }
    return $aRes;
}
function searchByKeyword($sKey, $aStations) {
    $aRes = array();
    foreach ($aStations as $i => $aInfo) {
        if (false !== strpos($aInfo['name'], $sKey) || false !== strpos($aInfo['desc'], $sKey)) {
            $aRes[$i] = $aInfo;
        }
    }
    return $aRes;
}

function parseStationList($aData) {
    $sStations = '';
    if (is_array($aData) && count($aData) > 0) {
        foreach ($aData as $i => $a) {
            $sStationId = $i;
            $sStationBr = (int)$a['br'];
            $sStationName = $a['name'];
            $sStationDesc = $a['desc'];
            $sStationUrl = $a['url'];

            $sThumb = 'media/'.($sStationId+1).'.png';
            $sStations .= <<<EOF
<li>
    <a href="{$sStationId}" onclick="return play('{$sStationId}'); return false;"><img alt="{$sStationName}" src="{$sThumb}" title="{$sStationName}"></a>
    <div class="i">
        <p>Bitrate: {$sStationBr}</p>
    </div>
    <p class="channel"><a href="{$sStationId}" onclick="return play('{$sStationId}'); return false;">{$sStationName}</a></p>
    <p class="track">{$sStationDesc}</p>
    <p class="label">{$sStationUrl}</p>
</li>
EOF;
        }
    }
    $sStations = ($sStations == '') ? '<li>Nothing found</li>' : $sStations;
    return '<ul>' . $sStations . '</ul>';
}

switch ($_GET['action']) {
    case 'play':
        $i = (int)$_GET['id'];

        $aInfo = $aStations[$i];
        $aVars = array (
            '__stream__' => $aInfo['stream'],
            '__title__' => $aInfo['name']
        );
        echo strtr(file_get_contents('templates/radio.html'), $aVars); exit;
        break;
    case 'get_genre_stations':
        $i = (int)$_GET['id'];

        $aSearch = searchByCat($i, $aStations);

        $sStations = parseStationList($aSearch);
        header('Content-Type: text/html; charset=utf-8');
        echo $sStations; exit;
        break;
    case 'get_keyword_stations':
        $sKey = $_GET['key'];

        $aSearch = searchByKeyword($sKey, $aStations);

        $sStations = parseStationList($aSearch);
        header('Content-Type: text/html; charset=utf-8');
        echo $sStations; exit;
        break;
}

$sLastStations = parseStationList($aStations);
echo strtr(file_get_contents('templates/main_page.html'), array('__stations__' => $sLastStations));

At the beginning, I have prepared list of our radio stations (4 stations total). Then – two search functions: ‘searchByCat’ and ‘searchByKeyword’. After – special function ‘parseStationList’ which will transform array with filtered stations into its HTML representation. And, at the end – little switch case to manage with our inner ajax commands.


Live Demo

Conclusion

You are always welcome to enhance our script and share your ideas. I will be glad to see your thanks and comments. Good luck!