#!/usr/bin/perl

##################################################
#
# GiantDisc mp3 Jukebox
# 
# © 2000-2004, Rolf Brugger
#
##################################################


# gdplaytimefilter.pl: Giant Disc play time filter
# reads play time state from mpg123 (stdin) and writes it to tmp/gdplaytime.txt
#

# we need to read the mpg123 status char by char. \r must be interpreted
# as line end (translation \r -> \n in a pipe with 'tr' is not possible,
# because tr writes buffered to stdout. But we need undelayed response.)


use lib '/home/music/bin';
use gdgentools;
use FileHandle;	    # to set auto flush on pipe
use DBI;
use strict;


### Parameters
if(scalar(@ARGV) != 5){print("gdplaytimefilter.pl needs 5 parameters (db-host, player-id, audiochannel, tracklength, player-app)\n");}
my $dbhost   = $ARGV[0]; 
my $playerid = $ARGV[1];
my $audiochannel = $ARGV[2]; 
my $tracklength  = $ARGV[3]; 
my $playerapp    = $ARGV[4]; 

my ($dbh);

### open DB connection
if ($dbhost eq "test"){
  print "playtimefiler: test mode\n\n";
}
else{
  $dbh = DBI->connect("DBI:mysql:GiantDisc:".$dbhost, "music", undef)
      or die "unable to connect to GiantDisc db";
}

### set termination handler
$SIG{TERM} = sub { print "playtimefilter.pl killed\n"; $dbh->disconnect; exit;}; # set Kill event handler


#print ("Play Time Filter started\n");

my ($char, $line, $frames, $framesrem, $framestotal, $matched, $writtenat, $ret);
my ($min, $sec, $tsec, $hsec);

autoflush STDIN 1;

### Get mpg123 verbose output
while(1){
  $ret = 1;
  $matched = 0;

  while (   $writtenat == time()   # only exit once in a second
         || !$matched              # only exit if line matched
        ){ 
    $line = "";
    while (1){
      $ret = read STDIN, $char, 1;
      last if ($ret==0 || $char eq "\r" || $char eq "\n");
      $line .= $char
    }
    last if ($ret == 0);
    #print("line recieved: '$line' \n");
    $frames = 0;
    $framestotal = 0;
    $matched = 0;
  
    if ($playerapp eq "mpg123"){
      #*** Get 'mpg123' verbose output
      #*   Example of an output line:
      #*   Frame#   210 [14226], Time: 00:05.48 [06:11.61],
      if ($line =~ m/Frame.*\s([0-9]+)\s*\[\s*([0-9]+)\]/){
        #print("mpg123 line matched: frames=$1 rem=$2\n");
        $frames=$1;
        $framesrem=$2;
        #$framestotal = $frames+$framesrem;
        $framestotal = time2frames(0,$tracklength,0);  # prefer this method because mpg123 can't reliably calc total time for vbr tracks
        $matched = 1;
      }
    }
  
    elsif ($playerapp eq "ogg123"){
      #*** Get 'ogg123' verbose output
      #*   Example of an output line:
      #*   Time: 00:03.78 [05:36.04] of 05:39.83  ( 96.9 kbps)  Output Buffer  96.9%
      if ($line =~ m/Time:\s*(\d+):(\d+)\.(\d+)\s*\[\d+:\d+.\d+\]\s*of\s*(\d+):(\d+)\.(\d+).*/){
        #print("ogg123 line matched: min=$1 sec=$2 hsec=$3 / min=$4 sec=$5 hsec=$6\n");
        $frames   = time2frames($1,$2,$3);
        $framestotal = time2frames($4,$5,$6);
        $matched = 1;
      }
    }
  
    elsif ($playerapp eq "mplayer"){
      #*** Get 'mplayer' verbose output
      #*   Example of an output line:
      #*   A:       1:09.9  3.8% 0%   ^M
      if ($line =~ m/A:\s*((\d*):)?(\d+).(\d+)\s.*/){
        #print("mplayer line matched: min=$2 sec=$3 tsec=$4\n");
        $frames   = time2frames($2,$3,10*$4);
        $framestotal = time2frames(0,$tracklength,0);
        $matched = 1;
      }
    }
  
    elsif ($playerapp eq "l2send"){
      #*** Get 'l2send' (BlueMP3) verbose output
      #*   Example of an output line:
      #*     [##---------------] 0:13, 125 kbit/s  ^M
      if ($line =~ m/\D*(\d+):(\d+)\D.*/){   # \D: nondigit,  \d: digit
        #print("l2send line matched: min=$1 sec=$2\n");
        $frames   = time2frames($1,$2,0);
        $framestotal = time2frames(0,$tracklength,0);
        $matched = 1;
      }
    }
  }

  if ($matched){
    if ($dbhost eq "test"){
      print "write playtime: dbh, playerid=$playerid, frames=$frames, framestotal=$framestotal\n";
    }
    else{
      #print "write playtime: dbh, playerid=$playerid, frames=$frames, framestotal=$framestotal\n";
      gdgentools::pll_write_playtime($dbh, $playerid, $audiochannel, $frames, $framestotal);
    }
  }
  $writtenat = time();
  #print "written at $writtenat seconds\n";

}

print ("Terminated: Playtime filter\n");


sub time2frames{
  my ($min,$sec,$hsec) = @_;
  use integer;
  return ((($min*6000)+($sec*100)+$hsec) * 441) / 1152;
}
#
