#!/usr/bin/perl #
# Music.pl version 0.6 #
# Sam Heller (sheller@marlboro.edu) #
# 10/28/03 #
# #
# This script works in conjunction with #
# a MySQL Database created by Register.pl #
# To query the mp3's available on your hard #
# drive, and present a web based interface #
# to stream them to any computer with an mp3 #
# player capable of receiving streams. #
# #
# Problems With This Version : #
# - Full ICY protocol is not implemented #
# - Only capable of streaming playlists #
# - Not able to package metadata with streams #
# - Port Numbers are not randomly generated #
# - Probably plenty more I don't remember #
# #
# This is not meant to be a functional version #
# at this point, but it's getting there. #
#==============================================#
#===========================================#
# Socket For Streaming #
# DBD::mysql For interfacing w/ mysql db #
# CGI For generating web frontend #
#===========================================#
use Socket;
use DBD::mysql;
use CGI;
#================================#
# See if we've got a stream to #
# serve up, otherwise, go to the #
# web frontend #
#================================#
$Stream = $page->param("Stream");
if ($Stream) { &Stream ; }
else { &Web ; }
sub Web
{
#============================================#
# Open up the Connection to the MySQL DB and #
# create the web page object. Also grab any #
# input that may be coming from the webpage #
#============================================#
$dbh = DBI->connect("DBI:mysql:music","root","") or die "Can't connect to MySQL DB : $!";
$page = new CGI;
$Band = $page->param("BandRequest");
$BandID = $page->param("BandID");
$AlbumID = $page->param("AlbumID");
$New = $page->param("New");
$BandName = $page->param("BandName");
$AlbumName = $page->param("AlbumName");
#========================================#
# If we are getting a fresh query, grab #
# the Band names and ID's from the MySQL #
# DB and push them into the arrays #
# @BandName and @BandID. #
#========================================#
if ($New)
{
$sth = $dbh->prepare("SELECT * FROM Band");
$sth->execute();
my @BandName;
my @BandID;
$x = 0;
while ($ref = $sth->fetchrow_hashref())
{
push (@BandName, $ref->{'BandName'});
push (@BandID, $ref->{'BandID'});
}
#=============================================#
# Print out the page headers and info, then #
# loop through all the entries and list the #
# Bands with hyperlinks to query this script #
# again. We need to autoincrement $x so that #
# The BandID can be synced with the Band Name #
#=============================================#
print $page->header( "text/html" ),
$page->start_html( "Band Listings" ),
$page->h1( "Band Listings" ),
$page->p( "These are the Bands currently available for streaming" );
foreach (@BandName)
{
print $page->br("$_");
$x++;
}
print $page->end_html;
$sth->finish;
$dbh->disconnect;
}
#=============================================#
# If the script is passed a BandID, troll the #
# MySQL DB, get all the albums from that band #
# that are available, and stick that and the #
# corresponding album ID into @AlbumName and #
# AlbumID. #
#=============================================#
elsif ($BandID)
{
$sth = $dbh->prepare("SELECT * FROM Album WHERE BandID=$BandID");
$sth->execute();
my @AlbumName;
my @AlbumID;
$x = 0;
print $page->header("text/html"),
$page->start_html("Album Listing"),
$page->h1("Album's Available");
while ($ref = $sth->fetchrow_hashref())
{
push (@AlbumName, $ref->{'AlbumName'});
push (@AlbumID, $ref->{'AlbumID'});
}
foreach (@AlbumName)
{
print $page->br("$_");
$x++;
}
print $page->end_html;
$sth->finish;
$dbh->disconnect;
}
elsif ($AlbumID)
{
$sth = $dbh->prepare("SELECT * FROM Song WHERE AlbumID=$AlbumID");
$sth->execute();
my @SongName;
my @SongPath;
my @TrackNumber;
my @TrackID;
$x = 0;
while ($ref = $sth->fetchrow_hashref())
{
push (@SongName, $ref->{'SongName'};
push (@SongPath, $ref->{'SongPath'};
push (@TrackNumber, $ref->{'TrackNumber'};
push (@TrackID, $ref->{'TrackID'};
}
print $page->header( "text/html" ),
$page->start_html( "Track Listing" ),
$page->h2( "Track Listing" );
foreach (@SongName)
{
s/.mp3//;
print $page->br("Track $TrackNumber[$x] :$_ ID=$TrackID[$x]");
$x++;
}
print $page->end_html;
$sth->finish;
$dbh->disconnect;
}
else
{
print $page->header( "text\html" ),
$page->start_html( "Error" ),
$page->h2( "Your Input was Invalid" ),
$page->end_html;
}
}
sub Stream
{
#======================================#
# Open up the connection to the server #
# and declare our variables #
#======================================#
$dbh = DBI->connect("DBI:mysql:music","root","") or die "Couldn't Open DB : $!" ;
my @SongName;
my @SongPath;
my @TrackPath;
#======================#
# Configure the socket #
#======================#
$port = 8080;
$domain = PF_INET;
$type = SOCK_STREAM;
$proto = getprotobyname('tcp') ;
$sockaddr = sockaddr_in($port, INADDR_ANY);
#==========================#
# Open and Bind the Socket #
#==========================#
socket (CLIENT, $domain, $type, $proto) or die "socket : $!\n";
bind(CLIENT, $sockaddr) or die "bind : $!\n";
#==================================================#
# Grab the Album info from the MySQL DB using #
# AlbumID, put together the full path of the song, #
# and push it onto the array @Playlist. #
#==================================================#
$sth = $dbh->prepare("SELECT * FROM Song WHERE AlbumID = $AlbumID");
$sth ->execute();
while ($ref = $sth->fetchrow_hashref())
{
$buffer = join '', $ref->{'SongPath'} , $ref->{'SongName'};
push (@Playlist, $buffer);
}
$sth->finish;
$dbh->disconnect;
#===============================#
# Open the socket and assign it #
# to fileandle HANDLER. #
#===============================#
listen(CLIENT, SOMAXCONN) or die "listen : $!\n";
$sockaddr = accept(HANDLER, CLIENT) or die "accept : $!\n";
($port, $ip_addr) = sockaddr_in($sockaddr) or die "new $!\n";
#===================================================#
# Once the client has connected, send them the #
# initial ICY dialouge, then open up the playlist #
# and start serving up the music. This is in no way #
# way complete at this point. I still need to #
# implement the full ICY protocol instead of sorta #
# half assing it, and I'd like to be able to send #
# the song's metadata along with the file. #
#===================================================#
print HANDLER "HTTP/1.0 200 OK\n\n";
foreach ( @Playlist )
{
open MP3, $_ or die "Couldn't Open $_ for reading : $! \n";
while (read MP3, $buffer, 8192)
{
print HANDLER $buffer;
}
close MP3;
}
close CLIENT;
}