#!/usr/bin/env perl
# MPlayer wrapper by Loren Merritt
# Implements '-alang' and '-slang' for OGM.
# note: the lang codes are case-insensive prefix matches,
#  not the 2- or 3-letter codes used by DVD or Matroska.
#
# Also disables internal subs when loading and external sub file,
# and downmixes 5.1 AAC in matroska.
#  
# Last updated: 2004-7-26

$^W=1;
use strict "refs";
use strict "subs";

# don't search $ENV{PATH} because I name this script 'mplayer' also.
foreach('/usr/local/bin/mplayer', '/usr/bin/mplayer') {
  -e $_ and $mplayer = $_ and last;
}
$mplayer or die "can't find mplayer in /usr/bin or /usr/local/bin\n";
$dotconf = "$ENV{HOME}/.mplayer/config";

sub mplayer() {
  if($ogm or $mkv) {
    print join(' ', $mplayer, @ARGV), "\n";
  }
  exec($mplayer, @ARGV);
}

for(@ARGV) {
  $ogm = $_ if /\.ogm$/ and !defined($ogm);
  $mkv = $_ if /\.mkv$/ and !defined($mkv);
  $aided ||= /^-aid$/;
  $sided ||= /^-sid$/;
  $noautosub ||= /^-noautosub$/;
}

if($ogm and $mkv) {
  die "track selection for multiple files not yet implemented\n";
} elsif(!$ogm and !$mkv) {
  mplayer();
} elsif(!-e ($ogm or $mkv)) {
  die "file doesn't exist: " . ($ogm or $mkv) . "\n";
}

$prev = '';
for(@ARGV) {
  if($prev =~ /^-alang$/) {
    # trailing comma means accept any langauge
    @alang = split(/,/, $_, -1);
    # turn off subs if alang=English and no slang specified.
    $nosubs ||= /(^|,)en/i;
  }
  if($prev =~ /^-slang$/) {
    @slang = split(/,/, $_, -1);
  }
  $prev = $_;
}
$nosubs = 0 if $sided or @slang;

# turn off internal subs if an external sub file exists
if(!@slang && !$sided && !$nosubs && !$noautosub) {
  ($base = $ogm || $mkv) =~ s/\.(?:ogm|mkv)$//i;
  if(grep {/^-sub$/} @ARGV or grep {-f "$base.$_" and -s _} qw/srt ssa sub/) {
    $sided = 1;
    unshift @ARGV, qw/-sid 99 -slang none/;
} }

if($nosubs && !$sided) {
  $sided = 1;
  unshift @ARGV, qw/-sid 99 -slang none/;
  if(!$noautosub) {
    unshift @ARGV, '-noautosub';
} }

#mplayer() unless $ogm;

if(not(($aided || @alang) && ($sided || @slang)) and -f $dotconf) {
  if(open CFG, "<", $dotconf) {
    while(<CFG>) {
      if(!@alang and /^\s*alang\s*=\s*([^#]+?)\s*$/i) {
	@alang = split /,/, $1, -1;
      }
      if(!@slang and /^\s*slang\s*=\s*([^#]+?)\s*$/i) {
	@slang = split /,/, $1, -1;
      }
    }
    close CFG;
  } else {
    warn "can't read '$dotconf': $!";
} }

s/^jpn?$/(jpn|ja?p)/i foreach(@alang, @slang);

if($mkv) {
  # downmix 5.1 audio
  # OGM doesn't support AAC, and mplayer automatically downmixes AC3
  @ARGV = grep {if($_ eq '-pan') {$pan=1; $nopan=0;}
	        elsif($_ eq '-nopan') {$nopan=1; $pan=0;}
		else {1}} @ARGV;
  if(!$pan and !$nopan) {
    # check whether the input contains 5.1
    open(INFO, '-|', 'mkvinfo', $mkv) or die "mkvinfo failed: $!\n";
    local $/ = " + A track\n";
    my @info = <INFO>;
    close INFO;
    LANG: foreach $lang (@alang ? @alang : '') {
      foreach (@info) {
	if(m/ \+ Codec ID: A_AAC/ and m/ \+ Language: $lang/) {
	  $pan = (m/ \+ Channels: 6\n/);
	  last LANG;
  } } } }
  if($pan) {
    unshift @ARGV, qw/-af pan=6:.32:.39:.06:.17:-.17:.33:.32:.06:.39:-.17:.17:.33,volume=10/;
} }

if($ogm && !($aided && ($nosubs || $sided))) {
  # OGM doesn't support -alang/-slang, so convert to -aid/-sid
  open(INFO, '-|', 'ogminfo', '-v', $ogm) or die "ogminfo failed: $!\n";
  $i=0;
  while(<INFO>) {
    last if ++$i>100 and /granulepos/;
    $info .= $_;
  }
  close INFO;
  $info or die "ogminfo failed\n";
  
  unless($aided) {
    foreach $alang (@alang) {
      if($info =~ m#\(a(\d+)/serial (\d+)\).+a\1:\s*LANGUAGE=(?i:$alang)#s) {
        unshift @ARGV, '-aid', $1-1;
        last;
  } } }
  
  unless($nosubs || $sided) {
    foreach $slang (@slang) {
      if($info =~ m#\(t(\d+)/serial (\d+)\).+t\1:\s*LANGUAGE=(?i:$slang)#s) {
        unshift @ARGV, '-sid', $1-1;
        last;
} } } }

mplayer();
