#!/usr/bin/perl -w
use strict;

use IPC::Open2;
use IO::Prompt;
use Term::ReadKey;

my $FLAC_FILE = shift;
my $TRACK = shift || 1;

$|++;

# get the track start positions from the embedded cuesheet
open my $CUESHEET, "metaflac --export-cuesheet-to - $FLAC_FILE |";

my @position_for_track;
my $i = 1;
while (<$CUESHEET>) {
    if (my ($m,$s,$f) = /INDEX 01 (\d\d):(\d\d):(\d\d)/) {
	$position_for_track[$i] = ($m * 60) + $s + ($f / 75);
	$i++;
    }
}

close $CUESHEET;


my $track_count = scalar @position_for_track - 1;
print "$track_count tracks\n";

die "There is no track $TRACK" if $TRACK < 1 or $TRACK > $track_count;

    
# launch the flac123 player as a daemon
my $flac123_pid = open2(my $PLAYER_OUT, my $PLAYER_IN, qw{flac123 -R});

print "flac123 PID = $flac123_pid\n";

my $current_track = $TRACK;
my $next_track_start = $position_for_track[$current_track + 1];

print "Track $current_track\n";

my %commands = (
    z => sub {
        return if $current_track <= 1;
        $current_track--;
        $next_track_start = $position_for_track[$current_track + 1];
        my $position = $position_for_track[$current_track];
        print $PLAYER_IN "JUMP $position\n";
        print "Track $current_track\n";
    },
    x => sub {},
    c => sub {},
    v => sub {},
    b => sub {
        return if $current_track >= $track_count;
        $current_track++;
        $next_track_start = $position_for_track[$current_track + 1];
        my $position = $position_for_track[$current_track];
        print $PLAYER_IN "JUMP $position\n";
        print "Track $current_track\n";
    },
    q => sub {
        print $PLAYER_IN "QUIT\n";
        ReadMode 'restore';
        exit;
    },
);


print $PLAYER_IN "LOAD $FLAC_FILE\n";
print $PLAYER_IN "JUMP $position_for_track[$TRACK]\n";

ReadMode 4;

while (<$PLAYER_OUT>) {
    # do a non-blocking read to see if the user pressed a key
    my $cmd = ReadKey -1;
    if (defined $cmd && exists $commands{$cmd}) {
        $commands{$cmd}->();
    }

    if (/\@F (\d+) (\d+) (\d+\.\d\d) (\d+\.\d\d)/) {
        my ($frame, $frames_left, $time, $time_left) = ($1, $2, $3, $4);
        if (defined $next_track_start && $time >= $next_track_start) {
            $current_track++;
            $next_track_start = $position_for_track[$current_track + 1];
            print "Track $current_track\n";
        }

=begin

        for (my $track_number = $track_count; $track_number > 0; $track_number--) {
            #warn $track_number;
            if ($position_for_track[$track_number] <= $time) {
                $current_track = $track_number;
                #print "Track $current_track\n";
                last;
            }
        }        

=cut

    }
}
    
waitpid $flac123_pid, 0;

ReadMode 'restore';

=begin flac123 -R outputs

@R FLAC123
flac123 tagline. Output at startup.

@I ID3:<a><b><c><d><e><f>
Prints out the metadata information after loading the flac file.
a = title (30 chars)
b = artist (30 chars)
c = album (30 chars)
d = year (4 chars)
e = comment (30 chars)
f = genre (30 chars)

@I filename
Prints out the filename of the flac file, minus the extension. Happens after
a flac file has been loaded and there is no metadata available.

@F <current-frame> <frames-remaining> <current-time> <time-remaining>
Frame decoding status updates (once per frame).
Current-frame and frames-remaining are integers; current-time and
time-remaining floating point numbers with two decimal places.

@P {0, 1, 2}
Stop/pause status.
0 - playing has stopped. When 'STOP' is entered, or the flac file is finished.
1 - Playing is paused. Enter 'PAUSE' or 'P' to continue.
2 - Playing has begun again.

=cut
