#!/usr/bin/perl -w
# $Rev$
# this is a cgi-bin wrapper around get_iplayer and provides a mainly point 
# and click interface for get_iplayer	http://linuxcentre.net/getiplayer
# it's still pretty crude but works well on the authors's linux home file 
# server. it's kind of grown from a very short simple script I knocked up 
# one friday evening. I hacked on a lot of new functionality specifically 
# because I bought a PS3 and it won't play flv directly. 
# you'll need to download and unpack the JFW flash video player if you 
# want to use this script to make the downloaded iplayer flv's be playable 
# through a web browser - find it at
#	http://www.longtailvideo.com/players/jw-flv-player/


use strict;
use CGI qw(:standard);
use URI::Escape;
use Filesys::Df;
use POSIX ":sys_wait_h";
use FileHandle;
use HTML::Entities;

require ('cgi_get_iplayer.pm');		# configuration values
# all the personalisation necessary should be in the .pm file, and there 
# should be no need to change this .pl script

our $cgiDir;
our $cgiWrapper;
our $baseURL;
our $dbgLevel;
our $flashHeight;
our $flashWidth;
our $httpProxy;
our $iplayerDir;
our $JwPlay6Key;
our $smbLocation;
our $uriFlv6;
our $uriFlvJS6;
our $uriFlv5;
our $uriFlvSWF5;
our $uriFlvJS5;


our $listerTv;
our $listerRadio;
our $updater;
our $downloader;
our $flvCommand;

###############################################################################
# shouldn't need to change anything below this line

# minimise delays writing to the browser
$| = 1;
STDERR->autoflush;	    # already unbuffered in stdio

my $p_func	= 'downloaded';	# the default page/function

###############################################################################
sub debugPrint
{
	my ($level, $dbgText) = @_;

	print "<i>Debug: $dbgText</i>\n<br />\n" if ($level < $dbgLevel);
}

###############################################################################
sub	runDownload
{
	my ($index, $mode, $forceRedownload, $transcodeAfter) = @_;

	my $cmd = "$downloader --modes $mode";
	$cmd = $cmd . " --force"	if ($forceRedownload);
	$cmd = $cmd . $flvCommand	if ($transcodeAfter);

	$cmd = $cmd . " -g $index";
	my $pid = fork();
	if (!$pid)
	{
		$| = 1;		# stdout is now a pipe, make it unbuffered too
		print "Attempting to execute command <i>" . encode_entities($cmd) . "</i>\n<br />\n";
		#if (open(FH, "$cmd 2>&1 &|"))
		if (open(FH, "-|", "stdbuf -oL -eL $cmd 2>&1"))
		{
			$| = 1;		#make the pipe output unbuffered too
			print "<pre>";
			while(<FH>)	# read output from the background process
			{
				print $_;
				flush STDOUT;
			}
			print "</pre>";
		}
		else
		{
			print "Failed executing command $cmd, error $?\n<br />\n";
		}
		exit;
	}
	else
	{
		print "Downloading in background, process ID $pid<br/>checking for process containing string '$downloader'<br/>\n";
		my $kid;
		do {
			print "...please wait...<br />\n<i>";
			#system("ps -ef | grep '$downloader' | grep -v grep");
			system("ps -ef | grep '-g $index' | grep -v grep");
			#system("ls -la $iplayerDir/*$bbcurl*");
			print "</i>\n<br />\n";
			$kid = waitpid(-1,WNOHANG);
			sleep 5;
			flush STDOUT;
		} while $kid == 0;

		print "<hr/>\n<a href=\"$cgiWrapper?func=downloaded\">back to main page</a>\n";
	}
}

###############################################################################
sub	updateListings
{
	my $cmd = "$updater";
	print "<h2>Updating list of available programs</h2>\n";
	debugPrint(2, "Debug: using command <i>$cmd</i>\n<br />\n");
	if (open(FH, "$cmd 2>&1 &|"))
	{
		$| = 1;		#make the pipe output unbuffered too
		print "<pre>";
		while(<FH>)	# read output from the background process
		{
			print $_;
			flush STDOUT;
		}
		print "</pre>";
	}
	else
	{
		print "Failed executing command $cmd, error $?\n<br />\n";
	}
}

###############################################################################
sub	showJwPlay5
{
	my ($p_file) = @_;

print<<EOF;
	<script type="text/javascript" src="$uriFlv5/$uriFlvJS5"></script>
	<embed flashvars="file=$baseURL/$p_file\&autostart=true"
		autostart="false"
		stretching="fill"
		allowfullscreen="true"
		allowscripaccess="always"
		id="player1"
		name="player1"
		src="$uriFlv5/$uriFlvSWF5"
		width="$flashWidth"
		height="$flashHeight"
	/>
EOF

}

###############################################################################
sub	showJwPlay6
{
	my ($p_file) = @_;

print<<EOF;
<script type="text/javascript" src="$uriFlv6/$uriFlvJS6"></script>
<script type="text/javascript">jwplayer.key="$JwPlay6Key";</script>
<div id="myElement">Loading the player...</div>

<script type="text/javascript">
    jwplayer("myElement").setup({
        file: "$baseURL/$p_file",
	fallback: true
    });
</script>

EOF

}
###############################################################################
sub	showActivity
{
	print "here's the current activity\n<pre>";
	system ("ps -efwl | grep '$downloader' | grep -v grep");
	print "</pre>\n";
}
###############################################################################
sub	showDownloaded
{
	chdir $iplayerDir;
	print "<h2>Downloaded Programs Ready To Play</h2>\n<br />\n";

	print "<form method=\"get\" action=\"\" />\n<input type=\"checkbox\" name=\"enable_delete\" />Enable Delete&nbsp;&nbsp;&nbsp;<input type=\"checkbox\" name=\"delete_image\" />Delete Associated Image\n<br /><br />\n";

	foreach my $indexLetter ("0", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z") 
	{
		print "<a href=\"#" . $indexLetter . "\">" . $indexLetter . "</a>&nbsp;&nbsp;";
	}
	print "<br />\n";


	print "<table border=\"0\">\n";
	print "<tr>\n<th>&nbsp;</th>\n<th>JW<br/>\nPlayer5&nbsp;&nbsp;</th>\n<th>JW <br/>\nPlayer6&nbsp;&nbsp;</th>\n<th>Download&nbsp;&nbsp;</th>\n<th>Delete?&nbsp;&nbsp;</th>\n<th>Size&nbsp;&nbsp;</th>\n<th>Date&nbsp;&nbsp;</th>\n<th align=\"left\">Title</th>\n</tr>\n";
	my @files = <*>;
	my $indexLetter='';
	foreach my $file (@files)
	{

		if ( (! -d $file) && ($file !~ /\.jpg$/ ) )
		{
			print "<tr>\n";

			my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($file);
			if ( param('enable_delete') && param("delete_$ino"))
			{
				#print "<td>DELETING</td>\n";
				unlink $file;
				if ( param('delete_image') )
				{
				    my $imgFile = $file;
				    $imgFile =~ s/\.flv/\.jpg/i;
				    if ( -f $imgFile )
				    {
					unlink $imgFile;
				    }
				}
				next;
			}


			$indexLetter = uc substr($file, 0, 1) if ($indexLetter eq '');
			if ($indexLetter ne substr($file, 0, 1))
			{
				$indexLetter = uc substr($file, 0, 1);
			}
			print "<a name=\"" . $indexLetter . "\">\n";
			if (   ($file =~ /(.*)\.flv$/) || ($file =~ /(.*)\.mp4$/)
			    || ($file =~ /(.*)\.avi$/) || ($file =~ /(.*)\.mov$/)
			   )
			{
				if ( -f "$1.jpg" )
				{
				    print "<td><img src=\"$baseURL/" . $1 . ".jpg\"/></td>\n";
				}
				else
				{
				    print "<td>&nbsp;&nbsp;</td>\n";
				}
				print "<td align=\"center\"><a href=\"?func=jwplay5&file=" . uri_escape($file) . "\"><img src=\"/icons/movie.gif\" alt=\"Play5\" /></a>&nbsp;&nbsp;&nbsp;</td>\n";
				print "<td align=\"center\"><a href=\"?func=jwplay6&file=" . uri_escape($file) . "\"><img src=\"/icons/movie.gif\" alt=\"Play6\" /></a>&nbsp;&nbsp;&nbsp;</td>\n";
			}
			else
			{
				print "<td>&nbsp</td>\n";
				print "<td>&nbsp</td>\n";
				print "<td>&nbsp</td>\n";
			}


			my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime);
			$mon++;
			$mday++;
			$year += 1900;
			#$hour;
			#$min;
			print	  "<td align=\"center\"><a href=\"$baseURL/$file\" target=\"_new\"><img src=\"/icons/diskimg.gif\" /></a>&nbsp;&nbsp;&nbsp;</td>\n"
				. "<td align=\"center\"><input type=\"checkbox\" name=\"delete_$ino\" />&nbsp;&nbsp;&nbsp;</td>\n"
				. "<td align=\"center\">" . int ($size / 1024) . "K&nbsp;&nbsp;&nbsp;</td>\n"
				. "<td align=\"center\"><code>" . $year . '-' . ($mon <= 9 ? '0' : '') . $mon . '-' . ($mday <= 9 ? '0' : '') . $mday . '&nbsp;' . ($hour <= 9 ? '0' : '') . $hour . ':' . ($min <= 9 ? '0' : '') . $min . "</code>&nbsp;&nbsp;&nbsp;</td>\n"
				. "<td align=\"left\">$file</td>\n"
				. "</tr>\n";

			print	"<tr><td colspan=\"8\"><hr></td></tr>\n";
		}
	}
	print "</table>\n<input type=\"submit\" name=\"submit\" value=\"GO\" />\n</form>\n";
}
###############################################################################
sub	rewriteAvailableLineToDownloadLink
{
	my ($availLine) = @_;

	if ($availLine =~ /^(\d+):\s+(.*)$/)
	{
		print "<input type=\"submit\" name=\"index\" value=\"" . $1 . "\">&nbsp;&nbsp;" . $2;
	}
	else
	{
		print "&nbsp;&nbsp;&nbsp;&nbsp;" . $availLine;
	}
	print "\n";

	
}
###############################################################################
sub	showRadioListing
{

	print "<hr />\n<h1>Radio Listing</h1>\n";

	my $cmd = "$listerRadio";
	if (open(FH, "$cmd 2>&1 &|"))
	{
		$| = 1;		#make the pipe output unbuffered too
		print "<pre>";
		while(<FH>)	# read output from the background process
		{
			chomp;
			rewriteAvailableLineToDownloadLink($_);
			flush STDOUT;
		}
		print "</pre>";
	}
	else
	{
		print "Failed executing command $cmd, error $?\n<br />\n";
	}

}

###############################################################################
sub	showTvListing
{
	print "<h1>TV Listing</h1>\n";
	my $cmd = "$listerTv";
	if (open(FH, "$cmd 2>&1 &|"))
	{
		$| = 1;		#make the pipe output unbuffered too
		print "<pre>";
		while(<FH>)	# read output from the background process
		{
			chomp;
			rewriteAvailableLineToDownloadLink($_);
			flush STDOUT;
		}
		print "</pre>";
	}
	else
	{
		print "Failed executing command $cmd, error $?\n<br />\n";
	}


}
###############################################################################
sub	showAvailable
{
	print "<form method=\"get\" action=\"$cgiWrapper\">\n<input type=\"hidden\" name=\"func\" value=\"download\" />\n</br >\n";
	#print "Enter URL: <input type=\"text\" name=\"bbcurl\" size=\"40\" />";


#  --modes <mode>,<mode>,...        Recording modes: flashhd,flashvhigh,flashhigh,flashstd,flashnormal,flashlow,n95_wifi,flashaac,flashaachigh,flashaacstd,flashaaclow,flashaudio,realaudio,wma.  Use --modes=best to automatically select highest quality available.

	print	"Video/Audio Quality: <select name=\"mode\">\n"
		#. "<option value=\"flashhd\">flashhd</option>\n"
		. "<option value=\"best\">best</option>\n"
		. "<option value=\"---\">---video---</option>\n"
		. "<option value=\"flashhd\">flashhd</option>\n"
		. "<option value=\"flashvhigh\">flashvhigh</option>\n"
		. "<option value=\"flashhigh\">flashhigh</option>\n"
		. "<option value=\"flashstd\">flashstd</option>\n"
		. "<option value=\"flashnormal\">flashnormal</option>\n"
		. "<option value=\"flashlow\">flashlow</option>\n"
		. "<option value=\"---\">---audio---</option>\n"
		. "<option value=\"flashaachigh\">flashaachigh</option>\n"
		. "<option value=\"flashaacstd\">flashaacstd</option>\n"
		. "<option value=\"flashaudio\">flashaudio</option>\n"
		. "<option value=\"flashaaclow\">flashaaclow</option>\n"
		. "<option value=\"rtspaacstd\">rtspaacstd</option>\n"
		. "<option value=\"rtspaaclow\">rtspaaclow</option>\n"
		. "<option value=\"wma\">wma</option>\n"
		. "</select>\n<br />\n";

	print "Either click button below or enter number to download: <input type=\"text\" name=\"altIndex\" size=\"5\" /><br />\n"
	    . "Force redownload: <input type=\"checkbox\" name=\"force_redownload\" /></br >\n"
	    . "Transcode After: <input type=\"checkbox\" name=\"transcode_after\" /></br >\n"
	    . "<input type=\"submit\" name=\"GO\" value=\"GO\" />\n<br />\n";
	print "If flashhd mode fails, try a lower quality because it may be simply that the program wasn't available in that mode.\n<br/>\n";
	showTvListing();
	print "<br />\n<br />\n";
	showRadioListing();

	print "</form>\n";
}

###############################################################################

$p_func = param('func') if (defined (param('func')));

print "Content-type: text/html\n\n"
	. "<html><head><title>iplayer downloader wrapper</title>\n";

#if ($p_func eq "download") {
#	print "<script type=\"text/javascript\" src=\"/autoscroll.js\"></script>\n";
#}

print "</head>\n<body>\n";

debugPrint(2, "p_func is " . $p_func );

my $dfRef = df("/home/iplayer");
my $freeMegaBytes = int ($dfRef->{bavail} / 1024);
print "Disk space available: ";
if ($freeMegaBytes > 4096)
{
	print int ($freeMegaBytes / 1024) . 'GB';
}
else
{
	print $freeMegaBytes . 'MB';
}
print "\n<br />\n";

if ($p_func ne 'jwplay5')
{
	print "<a href=\"?func=available\">show available programs to download</a>\n<br />" if ($p_func ne 'available');
	print "<a href=\"?func=downloaded\">show programs already downloaded</a>\n<br />" if ($p_func ne 'downloaded');
	print "<a href=\"?func=update\">update list of available programmes</a>\n<br />"  if ($p_func ne 'update');
	print "<br />Note: the directory where the files are is <b><a href=\"$smbLocation\">$smbLocation</a></b> - paste this into windows explorer<br />\n<br />\n" if ((defined $smbLocation) && ($smbLocation ne ''));
}

if ($p_func eq 'available')
{
	showAvailable();
}
elsif ($p_func eq 'downloaded')
{
	showDownloaded();
}
elsif ($p_func eq 'update')
{
	updateListings();
}
elsif ($p_func eq 'download')
{
	chdir $iplayerDir;
	my $index = '';
	my $mode = defined param('mode') ? param('mode') : 'flashvhigh';
	if (defined(param('index')))
	{
		$index = param('index');
	}
	elsif (defined(param('altIndex')))
	{
		$index = param('altIndex');
	}
	if ($index ne '')
	{
		my $transcodeAfter = ( defined param('transcode_after') ) ? 1 : 0;
		my $forceRedownload = ( defined param('force_redownload') ) ? 1 : 0;
		runDownload($index, $mode, $forceRedownload, $transcodeAfter);
	}
}
elsif ($p_func eq 'jwplay5')
{
	if (defined(param('file') ))
	{
		my $p_file = param('file');
		if (defined(param('device') ))
		{
			if (param('device') eq 'tablet')
			{
				$flashWidth	= 416;		# half the size of BBC flashvhigh
				$flashHeight	= 234;
			}
		}
		else
		{
			print "<a href=\"$cgiWrapper?func=jwplay5\&device=tablet\&file=$p_file\">play half size on tablet</a><br/>\n";
		}
		showJwPlay5($p_file);
	}
}
elsif ($p_func eq 'jwplay6')
{
	if (defined(param('file') ))
	{
		my $p_file = param('file');
		if (defined(param('device') ))
		{
			if (param('device') eq 'tablet')
			{
				$flashWidth	= 416;		# half the size of BBC flashvhigh
				$flashHeight	= 234;
			}
		}
		else
		{
			print "<a href=\"$cgiWrapper?func=jwplay6\&device=tablet\&file=$p_file\">play half size on tablet</a><br/>\n";
		}
		showJwPlay6($p_file);
	}
}
else
{
# convert FLV to h264 in mp3 wrapper for android
#ffmpeg -i Bang2.flv   -c:a copy   -c:v libx264              -profile:v baseline    bang2.mp4
# process Bang2.flv    copy audo   transcode video to x264   use baseline x264      output file

	print "unknown function \"$p_func\"!<br /><br /><a href=\"$cgiWrapper?func=downloaded\">back to downloaded page</a>\n";
}

#if (($p_func eq "list")) # | ($p_func eq "update"))
#{	print "<hr />\n";
#	showDownloaded();
#
	#print "<hr />\n";
	#showActivity();
#}


print "</body>\n</html>\n";

