#!/usr/bin/perl -w
#
# Tooling with XMMS
#
# toys: lyrics!
# http://www.lyrics007.com/Sugababes%20Lyrics/Hole%20In%20The%20Head%20Lyrics.html
#
use Xmms;
use Xmms::Remote;
use Getopt::Long;
use MP3::Info;
use File::Basename;
use File::Find;
use POSIX;
use WWW::Mechanize;
use Data::Dumper;

my $mode = "what";
my $start = 0;
my $syncdir;

$|= 1;

GetOptions( "mode=s" => \$mode,
            "start!" => \$start,
            "syncdir=s" => \$syncdir ) or die "usage: $0 --mode=whatever";

my $remote = Xmms::Remote->new;

if ( !$remote->is_running and !$start ) {
    die "XMMS isn't running, or I can't contact it!";
}

if ( !$remote->is_running ) {
    my $pid = fork();
    if ( !$pid ) {
        setsid();
        exec( "/usr/bin/xmms" );
    } else {
        while ( !$remote->is_running ) {
            sleep 1;
        }
    }
}

my $pos = $remote->get_playlist_pos;

if ( $mode eq "kill" ) {
    $remote->playlist_delete( $pos );
} elsif ( $mode eq "what" ) {
    if ( !$remote->is_playing or $remote->is_paused ) {
        print STDERR "XMMS is stopped\n";
        exit;
    }

    my $file = $remote->get_playlist_file( $pos );

    exit unless $file;          # XXX ugleeee

    if ( $file =~ /^http/ ) {

        # go ask last.fm's remote control
        if ( $file =~ /last\.fm/ ) {
            $^W = 0;            # sigh
            my ( $session ) = $file =~ m/.*Session=([0-9a-f]+)/;
            my $agent = WWW::Mechanize->new( env_proxy => 1, autocheck => 1 );
            my $res = $agent->get( "http://www.last.fm/player/radio/np.php?session=$session" );
            if ( $res->is_success ) {
                my ( $artist, $album, $track ) = ( "", "", "" );
                my @bits = split( /[\r\n]+/, $res->content );
                for my $bit ( @bits ) {
                    if ( $bit =~ /^artist=(.*)$/ ) {
                        $artist = $1;
                    } elsif ( $bit =~ /^album=(.*)$/ ) {
                        $album = $1;
                    } elsif ( $bit =~ /^track=(.*)$/ ) {
                        $track = $1;
                    }
                }
                if ( $artist and $album and $track ) {
                    print "$artist\t$album\t$track\n";
                    exit;
                }
                # else fall through
            }
        }

        # http://klortho:8000/admin?mode=sources
        # see if we can get a listing from the web server
        #      print STDERR "Trying for ${file}admin?mode=sources\n";
        #      my $agent = WWW::Mechanize->new( env_proxy => 1, autocheck => 1 );
        #      my $res = $agent->get( $file . "admin?mode=sources" );
        #      if ( $res->is_success ) {
        #          print STDERR Dumper( $res );
        #      }
        # crude, and harsh, and a bit lumpy
        $file = $remote->get_playlist_title( $pos );

        if ( $file =~ /(.*)\ - (.*) \(Gronk\)/) {
            print "$1\t(streaming)\t$2\n";
            exit;
        }
    }

    my $tag = get_mp3tag( $file );
    my ( $artist, $album, $title );
    if (defined( $tag )) {
        $artist = $tag->{ARTIST};
        $album = $tag->{ALBUM};
        $title = $tag->{TITLE};

        # damn you people and your API-changing ways... it seems
        # MP3::Info doesn't merge the v1/v2 data any more. Bad
        # developer, no cookie.
        if ( ref $artist ) {
            $artist = $artist->[-1];
        }
        if ( ref $album ) {
            $album = $album->[-1];
        }
        if ( ref $title ) {
            $title = $title->[-1];
        }

    } else {
        my ( @bits ) = split( '/', $file );
        $title = pop @bits;
        $album = pop @bits;
        $artist = pop @bits;
    }

    $artist ||= "Unknown Artist";
    $album ||= "Unknown Album";
    $title ||= basename( $file );
    $title =~ s/\.mp3$//i;

    # WTF? NULLs as well? Give me a BREAK!
    $artist =~ s/\x0//g;
    $album =~ s/\x0//g;
    $title =~ s/\x0//g;

    $artist =~ s/_/ /g;
    $album =~ s/_/ /g;
    $title =~ s/_/ /g;

    print "$artist\t$album\t$title\n";
} elsif ( $mode eq "rename" ) {
    my $oldname = shift;
    my $newname = shift;

    return unless $remote->get_playlist_length;

    my $found = 0;

    for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) {
        my $current = $remote->get_playlist_file( $ppos );
        $current =~ s@//@/@g;   # no, really
        $current =~ s@/./@/@g;
        if ( $current eq $oldname ) {
            print " xmms-frob is replacing $ppos ($current) with $newname\n";
            $remote->playlist_delete( $ppos );
            $remote->playlist_add( [ $newname ] );
            $found++;
        }
    }

    print "Didn't find $oldname in playlist\n" unless $found;
} elsif ( $mode eq "rm" ) {
    my $oldname = shift;
    $oldname = getcwd() . "/$oldname" unless $oldname =~ m@^/@;
    for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) {
        my $current = $remote->get_playlist_file( $ppos );
        next unless $current;
        $current =~ s@//@/@g;   # no, really
        $current =~ s@/./@/@g;
        if ( $current eq $oldname ) {
            $remote->playlist_delete( $ppos );
            print "nuked $oldname from $ppos\n";
        }
    }
} elsif ( $mode eq "cleanup" ) {
    my %files;
    my $ppos = 0;
    while ( $ppos < $remote->get_playlist_length ) {
        my $current = $remote->get_playlist_file( $ppos );
        next unless $current;
        $current =~ s@//@/@g;   # no, really
        $current =~ s@/./@/@g;
        if ( defined($files{$current})) {
            print "deleted dupe $current at $ppos\n";
            $remote->playlist_delete( $ppos );
        } else {
            if ( ! -r $current ) {
                print "deleted non-file $current at $ppos\n";
                $remote->playlist_delete( $ppos );
            } else {
                $files{$current} = 1;
                $ppos++;
            }
        }
    }
} elsif ( $mode eq "sync" ) {
    if ( !defined( $syncdir )) {
        die "You need to tell me what to sync with!";
    }

    find( sub {
              my $file = $File::Find::name;
              return unless -f $file;

              # see if we already have the file
              for my $ppos ( 0 .. $remote->get_playlist_length - 1 ) {
                  my $current = $remote->get_playlist_file( $ppos );
                  next unless $current;

                  $current =~ s@//@/@g;   # no, really
                  $current =~ s@/./@/@g;

                  if ( $file eq $current ) {
                      print "matched $file\n";
                      return;
                  }
              }

              print "You don't appear to have $file\n";
              $remote->playlist_add( [ $file ] );

          }, $syncdir );
}
