#!/usr/bin/perl

# Kim's MP3 Script
# http://wiki.kwinters.org/index.php/BMPx-XChat-Perl
#
# Version: 1.3.2

use utf8;
use MP3::Info;
use Net::DBus;
use Audio::FLAC::Header;
use Ogg::Vorbis::Header::PurePerl;
use URI::Escape;

my $ver = "1.3.2";
my $scriptname = "BMPxInfo v$ver";
my $author = "kim";
my $lbra = "\0034[\00314";
my $rbra = "\0034]\00315";
my $dot = "\00304*\00314";
my $front = "\00315";
$sexydot = "*";

my $auto_announce = 1;
my ($index,$title,$filename,$announce,$plays);

my $bmp_server1 = "server1";
my $announce_chan1 = "#chan1";
my $bmp_server2 = "server2";
my $announce_chan2 = "#chan2";

IRC::command("/echo \0034:: $lbra$scriptname by $author Loaded$rbra \0034::");
IRC::register("$scriptname by $author", $ver, "", "");


my ($bus,$service,$bmpx);
$bus = Net::DBus->session;
$service = $bus->get_service("org.mpris.bmpx");
$bmpx = $service->get_object("/org/mpris/bmpx/SystemControl");

# Let's Use Signals Instead
$bmpx->connect_to_signal("TrackChange", \&song_handler);

IRC::add_command_handler("songsend","songsend_handler");
sub songsend_handler {
	my $snick = shift;

	if ($snick) {
		IRC::command("/dcc psend $snick \"$filename\"");
	}

	return 1;
}

IRC::add_command_handler("mp3","mp3_handler");
sub mp3_handler {
	IRC::command("/say $announce");
	return 1;
}

IRC::add_command_handler("plays","plays_handler");
sub plays_handler {
	IRC::command("/me plays $plays");
	return 1;
}

IRC::add_command_handler("song", "song_handler");
sub song_handler {
		my ($stuff);
		$index = $bmpx->GetCurrentTrack() + 1;
		$filename = $bmpx->GetCurrentUri();
		
		$filename =~ s/file:\/\///;
		$filename =~ s/[\n\r]//;
		$filename = uri_unescape($filename);

		if ($filename =~ /.mp3$/i) {
			my $info = MP3::Info->new($filename);
			$length = $info->{TIME};
			$bitrate = $info->{BITRATE} . " kbps";
			$sfreq = $info->{FREQUENCY} . " kHz";
			$size = $info->{SIZE};
			$size /= (1024*1024);
			$size = sprintf("%.2f",$size);
			my $tag = get_mp3tag($filename);
			$title = "$tag->{ARTIST} - $tag->{TITLE}";
			$announce = "${lbra}\#$index${rbra} ${lbra}$title${rbra} ${lbra}$length${rbra} ${lbra}$sfreq${rbra} ${lbra}$bitrate${rbra} ${lbra}$size" . "MB${rbra}";
			$plays = "$title ($length)";
		} elsif ($filename =~ /.ogg$/i) {
			my $ogg = Ogg::Vorbis::Header::PurePerl->new("$filename");
			my $ogginfo = $ogg->info;
			$sfreq = sprintf("%.1f kHz",$ogginfo->{rate}/1000);
			$length = sprintf("%2f",$ogginfo->{length});
			$bitrate = sprintf("%d kbps",$ogginfo->{bitrate_nominal}/1000);
			$length = oggtime($length);
			$size = getsize($filename);
			$title = "N/A";
			$announce = "${lbra}\#$index${rbra} ${lbra}$title${rbra} ${lbra}$length${rbra} ${lbra}$sfreq${rbra} ${lbra}$bitrate${rbra} ${lbra}$size" . "MB${rbra}";
			$plays = "$title ($length)";
		} elsif ($filename =~ /.flac$/i) {
			my $flac = Audio::FLAC::Header->new("$filename") || "Unreadable";

			if ($flac ne "Unreadable") {
				my $asdf1 = $flac->{trackLengthMinutes};
				my $asdf2 = $flac->{trackLengthSeconds};
				if ($asdf1 < 10) { $asdf1 = "0$asdf1"; }
				if ($asdf2 < 10) { $asdf2 = "0$asdf2"; }
				$length = "$asdf1:$asdf2";
				$bitrate = $flac->{bitRate};
				$bitrate = sprintf("%d kbps",$bitrate/1000);
				my $info = $flac->info();
				$sfreq = $info->{SAMPLERATE} / 1000;
				$sfreq = sprintf("%.1f kHz",$sfreq);
				my $tag = $flac->tags();
				$title = "$tag->{ARTIST} - $tag->{TITLE}";
				
			} else {
				$title = "N/A";
				$length = "N/A";
				$bitrate = "N/A";
				$sfreq = "N/A";
			}

			$size = getsize($filename);

			$announce = "${lbra}\#$index${rbra} ${lbra}$title${rbra} ${lbra}$length${rbra} ${lbra}$sfreq${rbra} ${lbra}$bitrate${rbra} ${lbra}$size" . "MB${rbra}";
			$plays = "$title ($length)";

		} else {
			$announce = "${lbra}\#$index${rbra} ${lbra}$title${rbra}";
			$plays = "$title";
		}
		if ($auto_announce) {
			IRC::command_with_server("/msg $announce_chan1 $announce", $bmp_server1);
			IRC::command_with_server("/msg $announce_chan2 $announce", $bmp_server2);
		}

        # No further parsing necessary
        return 1;
}


sub getsize {
		my $filename = shift;
		my ($filesize,@sizeinfo);
		if ($filename !~ /http:\/\//) {
			chomp($filesize = `ls -lh "$filename"`);
		}
		$filesize =~ s/\s+/ /g;
		$size = (split(/ /,$filesize))[4];
		$size =~ s/[^\d.]//g;
		return $size;
}

sub oggtime {
        my $time = shift;
        my ($min,$sec);
        $min = int($time / 60);
        if ($min < 10) { $min = "0$min"; }
        $time %= 60;
        $sec = int($time);
        if ($sec < 10) { $sec = "0$sec"; }
        return "$min:$sec";
}

IRC::add_command_handler("xmms","bmp_handler");
IRC::add_command_handler("bmp","bmp_handler");
sub bmp_handler {
    my $cmd = shift;
    if ($cmd eq "stop") {
		$bmpx->PlayStop();
        &msg("Stopped");
    }
	elsif ($cmd eq "play") {
        $bmpx->PlayCurrent();
        &msg("Playing");
   }
    elsif ($cmd eq "pause") {
		$bmpx->PlayPause();
		&msg("Paused");
    }
    elsif ($cmd eq "next") {
		$bmpx->PlayNext();
        sleep(1);
        &song_handler;
    }
    elsif ($cmd eq "prev") {
		$bmpx->PlayPrev();
        sleep(1);
        &song_handler;
    }
    elsif ($cmd =~ /^vol/) {
        my ($vol) = $cmd =~ m/vol (.*)/;
        if ($vol < 0 || $vol > 100 || $vol =~ /\D/) {
            &echo("$dot Volume must be between 0 and 100");
        }
        else {
            $bmpx->VolumeSet($vol);
            &msg("Volume: $vol");
        }
	}
	elsif ($cmd =~ /^jump/) {
		my ($n) = $cmd =~ m/jump (\d+)/;
		if ($n) {
			`bmpx-kim jump $n`;
			&msg("Jumping to #$n");
			sleep(1);
			&song_handler;
		}
    }
	elsif ($cmd =~ /^find/) {
        my ($regex) = $cmd =~ m/find (.*)/;
        if ($regex) {
			my (@list);
            chomp (@list = `bmpx-kim $regex`);
			if ($#list == 0) {
				&song_handler;
			} else {
				foreach (@list) {
					&echo("$_");
				}
			}
				
        }
    }
	elsif ($cmd eq "noauto") {
		$auto_announce = 0;
	}
	elsif ($cmd eq "auto") {
		$auto_announce = 1;
	}
	else {
		&echo("${lbra}BMPx${rbra} Current commands: stop, play, pause, next, prev, vol");
	}

	return 1;
}

sub msg {
    my $msg = shift;
    IRC::command("/say ${lbra}BMPx${rbra} $msg");
}

sub echo {
    my $msg = shift;
    IRC::command("/echo $dot $msg");
}

