<?
// PHPCast 0.0.2
// Mp3 streamer in PHP
//
// Original code and idea from Jordan Waeles (hide@address.com )
//
// Details of the stream
$stream['name'] = "PHPCast Stream"; /* Name of the stream */
$stream['genre'] = "various"; /* Genre of the stream */
$stream['url'] = "http://phpcast.sourceforge.net"; /* URL of the site hosting phpcast */
$stream['public'] = "1"; /* Set to 0 to make the server private */
$stream['bitrate'] = "128"; /* Set this to the bitrate of your mp3 files */
$stream['path'] = "data"; /* Path to the mp3 files. Relative or absolute */
// Configuration of the cache
$cache['active'] = true; /* Set to false to disable cache (up to 3x slower for tags extraction ) */
$cache['type'] = gdbm; /* Type of cache (gdbm, ndbm, db2, db3, db4)
depending on your php compile option */
$cache['directory'] = "cache"; /* Relative or absolute path to save cache files (beware of chmod) */
// Size of shoutcast frames
$taille = 8192;
/* You won't have to touch below for a normal setup */
@ini_set("max_execution_time", "0");
require_once'getid3/getid3.php';
require_once 'getid3/extension.cache.dbm.php';
// headers shoutcast
header("icy-notice1:This is a WINAMP ShoutCast Stream");
header("icy-notice2:You will only see binary data, please press STOP button");
header("icy-name:".$stream['name']);
header("icy-genre:".$stream['genre']);
header("icy-url:".$stream['url']);
if ($stream['public'] == "1") {
header("icy-pub:1");
}
else {
header("icy-pub:0");
}
header("icy-br:".$stream['bitrate']);
header("icy-metaint:".$taille);
// Function that alternates mp3 / data while keeping good sync
// (example 8192 bytes of mp3 - X bytes of meta data)
function streamfile($file, $randombegin=false, $offset=0)
{
GLOBAL $taille;
GLOBAL $debug;
GLOBAL $cache;
/* We start caching support (or not) */
if($cache['active'] == "true") {
$getID3 = new getID3_cached_dbm($cache['type'], $cache['directory']."/id3.dbm", $cache['directory']."/id3.lock");
}
else {
$getID3 = new getID3();
}
$fp = fopen($file,"rb");
if(!$fp)
die("Access denied for $file");
// number of bytes left to stream
$taillefichier = filesize($file);
// we begin in the middle of the mp3
if($randombegin)
{
$random = rand()%$taillefichier;
$taillefichier -= $random;
fseek($fp,$random);
}
// Title of current mp3 file
// Depending of ID3 tag version
$fileInfo = $getID3->analyze("$file");
if($fileInfo['id3v2']['comments']['title']) {
$title = "StreamTitle='".$fileInfo['id3v2']['comments']['title'][0]." - ".$fileInfo['id3v2']['comments']['artist'][0]."';StreamUrl='".$stream['url']."';\n\0";
}
elseif($fileInfo['id3v1']['title']) {
$title = "StreamTitle='".$fileInfo['id3v1']['title'][0]." - ".$fileInfo['id3v1']['artist'][0]."';StreamUrl='".$stream['url']."';\n\0";
}
else {
$title = "StreamTitle='".addslashes($file)."';StreamUrl='".$stream['url']."';\n\0";
}
// generating appropriate header
$tailletitre = strlen($title);
$headersize = ceil( (float)$tailletitre / 16.0 );
$headerbyte = chr($headersize);
// while we aren't at the end of the file
while(!feof($fp))
{
// we read $taille data( except if we begin with
// the end of an other file )
$meuh = fread($fp,$taille-$offset);
if(!$debug)
{
// mpeg stream
echo $meuh;
}
// we finished the file
if(feof($fp))
{
// we might have to add data to have
// 8192 bytes of mpeg
$offset = $taillefichier;
}
else
{
// and we count what has already been streamed
$taillefichier -= $taille;
// delay is cancelled for next turn,
// packets are $taille now !
$offset = 0;
if(!$debug)
{
// the first byte is title length / 16 ,
// then if the titre is 64 bytes long, we'll have 4 (0x04)
echo $headerbyte;
// the title
echo $title;
// if it doesn't fill $headerbyte * 16 bytes,
// we put random data for the byte to be the
// right length ( ici un A, ca marche avec un espace aussi ,
// meme s'il est recommandé de le faire avec des 0 binaires
// ( 0x00 ) mais je ne sais pas comment php l'interprete ,
// et ca semble marcher ainsi )
for($i=$tailletitre;$i<($headersize*16);$i++)echo chr(65);
}
}
}
fclose($fp);
// We keep the delay for the next frame
$offset %= $taille;
if($offset < 0)$offset += $taille;
return $offset;
}
// Little ereg, that compares an string with
// *aster*is*ques with a normal string
function match($pattern, $string)
{
$stucks = explode("*",$pattern);
$str = $string;
for($i=0;$i<count($stucks);$i++)
{
$stuck = $stucks[$i];
if(empty($stuck))continue;
$pos = strpos($str,$stuck);
$str = stristr($str,$stuck);
if(($i==0)&&($pos != 0))return false;
if(!is_string($str))return false;
}
return true;
}
// initialisation of the random number generator
srand((float) microtime()*1000000);
// find all files in the mp3 folder
if ($handle = opendir($stream['path']))
{
// for each file
while (false !== ($file = readdir($handle)))
{
// if it's a read file ( no shortcut / directory )
if(is_file($stream['path']."/".$file))
{
// and that its name ends with .mp3 (case insensitive)
if(match("*.mp3",strtolower($file)))
{
// we put it in the playlist
$playlist[] = $stream['path']."/".$file;
}
}
}
// end !
closedir($handle);
}
else
die("Unable to open mp3 library !");
if(empty($playlist))
die("There aren't any mp3 files in this diretory !");
// don't touch !
$offset = 0;
// if it's true, we begin at a random position in the file
// User will have the feeling of listening to a real stream
$firstfile = true;
// infinite loop
while(true)
{
reset($playlist);
shuffle($playlist);
foreach($playlist as $item)
{
$offset = StreamFile($item, $firstfile, $offset);
if($debug)
{
echo $item."<br>";
echo "offset vaut maintenant $offset<br>";
}
// After the first song, we don't begin in the middle
$firstfile = false;
}
if($debug)
echo "--------- ended !!<br>";
}
?>