#!/opt/links/perl -w

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#     xmripper - A program to cut live XM into song chunks, in realtime. 
#                Connect your XM PCR to your sound card's
#                line input, select the line input for recording (with
#                aumix), and start recording. In another shell, you can
#                run 'bladeenc -del -192 *wav' in a continuous 'while' loop
#                to convert the files to mp3 while you're recording.
#
#                This program uses 2 directories: it records into $tempdir,
#                then moves the recording to $tempdir/$station when complete.
#                This application is subject to the same copyright as the
#                Audio::Xmpcr module.
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#                                configuration
my $tempdir="/burn/audio/xmdone";
my $nethost="localhost";
my $rate=44101;      # either 44100 or 44101; problem with some soundcards
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

use strict;
use bytes;
use Audio::DSP;
use Audio::Wav;
use Audio::Xmpcr;
use Fcntl;
die "usage: $0 station duration(mins)\n" if scalar(@ARGV)!=2;
my($station,$duration)=@ARGV;

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#                        set up the audio dev and output file
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
my $dsp = new Audio::DSP(
	buffer   => 65536,
  channels => 2,
  format   => 16,
  rate     => $rate,
  mode 		 => O_RDONLY,
) or die "Can't create a DSP object: $!";
$dsp->init(mode => O_RDONLY) || die "failed to init dsp: " . $dsp->errstr();

my $spooldir=$tempdir . "/$station";
chdir($tempdir) || die "$tempdir doesn't exist!";
mkdir($spooldir) if ! -d $spooldir; 
my $termtime=time+$duration*60;

my $radio=new Audio::Xmpcr(NETHOST => $nethost,LOCKER => "ripper")
									or die "Couldn't contact the XMPCR";
print "Turning radio power on...\n"; 
$radio->power("on") and die "can't turn power on";
print "Changing channel to $station\n"; 
$radio->setchannel($station) and die "Can't change the channel!";
$radio->events("on");
print "Ready to record... waiting for next song/title to begin... \n";

# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#                            main loop
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
my $wav=new Audio::Wav;
my $details={ bits_sample => 16, sample_rate => 44100, channels => 2 };
my($outfh,$outfn,$buf)=(undef,undef); # don't record initial partial song
while(time<$termtime) {
	$outfh->write_raw($buf) if $buf=$dsp->dread and $outfh;
	for my $ch ($radio->processEvents()) {
		next unless $ch->{NUM}==$station;
		save($outfn) if $outfh;
		$outfn=($ch->{ARTIST}||"none") . "_-_" . ($ch->{SONG}||"none");
		$outfn =~ s/ /_/g;                   # chuck all spaces
		1 while $outfn =~ s/__/_/g;          # double spaces to single
		$outfn =~ s/^_+//;                   # toss leading underscores
		print "> Song change: $outfn\n";
		$outfh=$wav->write($outfn . ".wav",$details);
	}
}
save($outfn) if $outfh;

sub save {
	$outfh->finish();
	rename("$tempdir/$outfn.wav","$spooldir/" .  # don't overwrite existing!
		$outfn . (-f "$spooldir/$outfn.wav" ? ("_" . time()) : "") . ".wav")
		or warn "Hmm.. had trouble saving $outfn: $!\n";
}
