#!/usr/bin/perl -w
#
# mpwait version 0.1
#
# Sleeps until mpd finishes the currently playing track. Requires mpc
# to be on the user's path.
#
# Written by Hannes Reich (hannesATskynetDOTie), 30/06/2005.
# This code is in the public domain.
#

use strict;
use sigtrap;
use constant {
  # Limits on how often mpd is polled. Subsecond values are ok.
  MIN_POLLING_INTERVAL => 0.2, # lower this for more accurate timing
  MAX_POLLING_INTERVAL => 5  # lower this to detect manual track
                             # changes faster, and for more accuracy
                             # on short tracks
};

use Time::HiRes qw(usleep);
use Shell qw(mpc);


my $current_track;
WAIT:
while(1)
  {
    my $sleep_seconds = MAX_POLLING_INTERVAL;

    my $mpc_output = join '', mpc;
    # match things like "[playing] #1/4086   0:00 (0%)"
    if($mpc_output =~ /^\[(playing|paused)\] \#(\d+)\/\d+\s+(\d+):(\d\d)\s+\((\d+)%/m)
      {
	my($status, $track, $minutes_played, $sub_minute_seconds_played, $percent_played)
	  = ($1, $2, $3, $4, $5);

	# remember the first track number we see
	$current_track = $track
	  unless defined $current_track;

	# bail if the track has changed
	last WAIT
	  if $current_track != $track;

	if('playing' eq $status and 0 < $percent_played)
	  { # check how much of this track is left to play, so we don't sleep for too long
	    my $seconds_played = ($sub_minute_seconds_played + $minutes_played*60);
	    my $seconds_length = 100 * $seconds_played / $percent_played;
	    my $seconds_remaining = $seconds_length - $seconds_played;

	    # shorten the sleep if needs be
	    $sleep_seconds = $seconds_remaining
	      if $sleep_seconds > $seconds_remaining;
	    # but don't go too short
	    $sleep_seconds = MIN_POLLING_INTERVAL
	      if MIN_POLLING_INTERVAL > $sleep_seconds;
	  }
      }

    die "MPD doesn't seem to be playing any track.\n"
      unless defined $current_track;

    usleep 1000000 * $sleep_seconds;
  }


