#!/usr/bin/perl -w

=head1 NAME
   abc2bars

=head1 SYNOPSIS
   abc2bars "title" [file]...  >foo.abc

=head1 DESCRIPTION
   This program reads through the input file(s), or stdin if no files
   are  named,  looking for abc tunes.  When it finds one, it outputs
   the first two bars of the tune, with the tune name in the place of
   the first "guitar chord".  Other chords are deleted.

   The resulting file can be fed to abc2ps or abcmtex  to  produce  a
   page of musical reminders of how the tunes start.

   Tunes  will  be  in  the  same  order  they  are  in  the   files.
   Alphabetical order is recommended, but any organization that makes
   sense to you may be used.

   The output contains abc2ps commands that will produce  very  small
   music and names.

=head1 BUGS
   If a tune contains no L: line, there will be none in  the  output,
   so  the  L: line from the preceding tune will be used.  This isn't
   always what you want.  Fix: Include L: lines in  all  your  tunes,
   even when they aren't needed.  This is always a good idea anyway.

   The T:, L: and K: lines must be at the  start  of  a  line  to  be
   recognized.

=head1 AUTHOR
   <a href="mailto:jc@trillian.mit.edu">John Chambers</a>
=cut

$| = 1;
($P = $0) =~ s".*/"";	# Our name, minus directories
$V = $ENV{"V_$P"} || 1;	# Verbose/trace/debug level
$exitstat = 0;			# Set to nonzero for failure

$title = shift || "Tunes";
#print "%%scale 0.4\n";
#print "%%maxshrink 1\n";
#print "%%staffwidth    16.0cm\n";
#print "%%leftmargin    2.0cm\n";
#print "%%topmargin     0.2cm\n";
#print "%%topspace      0.2cm\n";
#print "%%titlespace    0.0cm\n";
#print "%%composerspace 0.0cm\n";
#print "%%musicspace    0.0cm\n";
#print "%%staffsep      40\n";
print "%%maxshrink 1\n";
print "%%scale 0.4\n";

$minbars  =   2;	# Number of bars per tune
$minnotes =  11;	# Min number of notes required
$page     =   0;	# Page counter, for titles
$tunes    =   0;	# Tune counter, for page eject
$tpp      = 128;	# Max tunes per page
$tps      =   4;	# Number of tunes per staff

sub ttl {
	++ $page;
	print "\n";
	print "X: $page\n";
	print "T: $title p.$page\n";
	print "K: C\n";
	print "%\n";
}

$| = 1;
$t = 0;
$s = 0;	# State

for $f (@ARGV) {
	if (!open(F,$f)) {
		print STDERR "$0: Can't read \"$f\" [$!]\n";
		next;
	}
	$eol = "\\\n";
	while ($l = <F>) {
		$l =~ s/\s+$//;
		if ($l =~ /^T:\s*(.*)/) {
			$T[$t++] = $1;
			$s = 1;		# State: in header
		} elsif ($l =~ /^X:\s*\d+/) {
			$s = 1;		# State: in header
			$t = 0;		# Start over with new title
		} elsif ($l =~ /^L:\s*([\d\/]+)/) {
			$L = $1;
		} elsif ($l =~ /^K:\s*([\w\^_=]+)/) {
			if ($s == 1) {
				$K = $1;
				$s = 2;	# State: in music
			}
		} elsif ($l =~ /^[A-Z]:/) {
		} elsif ($l =~ /^%/) {
		} elsif ($s == 2) {
			if ($m = &strip($l)) {	# Do we have a line of music?
				$tunes ++;
				if (($tunes % $tpp) == 1) {
					&ttl;
				} elsif ($tps && ($tunes % $tps) == 0) {
#					print "%[EOL after $tunes tunes]\n";
					$eol = "\n";
				}
				$ttl = $T[0];
				print "[K:$K]\\\n";
				print "[L:$L]\\\n";
				$m =~ s/- \|$/ |/;	# Suppress final ties
				print "[|\"$ttl\"$m]$eol";
				$s = 3;				# State: Done with this tune
				$t = 0;				# Start over with new title
				print "P:\n" if $eol eq "\n";
				$eol = "\\\n";
			}
		}
	}
}
while ($tunes % $tps) {
	print "y8 y8 y8 y8 y8 y8\\\n";
	++$tunes;
}

exit 0;

sub strip {
	local($line) = @_;
	local($bars,$music,$notes,$x) = (0,'',0);
	$line = '' unless defined $line;
	while ($line =~ m/\\[r\s]*$/) {		# Continued?
		$line =~ s/\s*\\[r\s]*$/ /;
		if ($x = <F>) {
			$line .= $x;				# Append next line
		} else {
			print STDERR "$P/strip: EOF in \"$f\"\n" if $V>1;
		}
	}
	unless ($line) {
		print STDERR "$P/strip: EOF in \"$f\"\n" if $V>0;
		return $line;
	}
	while ($line) {
		if ($line =~ s'^\s+'') {		# White space?
			$music = $music . ' ' if $music;	# Convert to single space
		} elsif ($line =~ s'^"[^"]*"'') {		# Discard a chord
		} elsif ($line =~ s'^{[^}]*}'') {		# Discard grace notes
		} elsif ($line =~ s'^([A-Ga-g][\d\/\^_=\',]*)'') {	# Note?
			$music = $music . $1;
			++$notes;
#			$music .= "[$notes]";
		} elsif ($line =~ s/^(\[\||\|\]|:*\|+:*)//) {	# Bar line?
			if ($notes) {
				$music = $music . '|';
				++$bars
			}
			return $music if (($bars >= $minbars) && ($notes >= $minnotes));
		} elsif ($line =~ s/^\[([^]]*)\]//) {	# Chord?
			$music = $music . "[$1]";
			++$notes;
#			$music .= "[$notes]";
		} elsif ($line =~ s/^(.)//) {			# Anything else
			$music = $music . $1;
		}
	}
	$music;	# Ran off end of line
}
