package Plugins::ABC;

# SlimServer Copyright (c) 2001-2004 Sean Adams, Slim Devices Inc.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License,
# version 2.

# Created from many other scripts by Gerph (11 Oct 2005)
#
# Purpose:
#    Provides converting of ABC files through MIDI files to wave or mp3.
#
# Limitations:
#    It's a bit hacked together.
#
# Requirements/Installation:
#    This source - copy it into the Plugins directory
#    abc2midi - copy it into the Bin directory or install it in the path.
#          On debian, use 'apt-get install abc2midi'.
#    Timidity - copy it into the Bin directory or install it in the path.
#          On debian, use 'apt-get install timidity'; you might need the
#          sound patches too; 'apt-get install freepats'.
#          Be aware that this lot is big.
#    Lame - download and build yourself a copy, or obtain it some other
#           way. Try http://lame.sf.net/download/download.html
#           There does not seem to be a debian package for it.
#    Modifications to the custom-types.conf and slimserver-convert.conf files
#      - you can do this automatically by doing the following :
#          perl -MABC -e Plugins::ABC::AddTypes
#    Restarting the server.
#

###############################################################################
# FILE: Plugins::ABC.pm
#
# DESCRIPTION:
#     Fake some information just so that ABC files play. Not entirely accurate(!)
#
###############################################################################

use strict;

$Slim::Music::Info::tagFunctions{'abc'} = {
		'module' => 'Plugins::ABC',
		'loaded' => 1,
		'getTag' => \&Plugins::ABC::getTag,
};

our $config_artist = "[ABC]";
# Export the version to the server
use vars qw($VERSION);
$VERSION = "0.02";
# 0.01 (13 Oct 2005) - initial version created from MIDI.pm
# 0.02 (17 Oct 2005) - added artist grouping

sub getDisplayName { return 'PLUGIN_ABC' };

sub strings
{
    local $/ = undef;
    <DATA>;
}

# Given a file, return a hash of name value pairs,
# where each name is a tag name.
sub getTag {
	my $tags = {};

	my $file = shift || "";
	my $title;

	open (IN, "< $file") || return $tags;
	while (<IN>)
	{
	  if (/^T:(.*)\n/)
          { $tags->{'TITLE'} = $1;
            last; }
	}
	close(IN);

	$tags->{'ARTIST'} = $config_artist;
	$tags->{'STEREO'} = 2;

	$tags->{'SECS'} = -1; # We're going to lie, just so that we have a value
	$tags->{'SIZE'} = -s $file;

	# stolen from MP3::Info
	$tags->{'MM'}	    = int $tags->{'SECS'} / 60;
	$tags->{'SS'}	    = int $tags->{'SECS'} % 60;
	$tags->{'MS'}	    = (($tags->{'SECS'} - ($tags->{'MM'} * 60) - $tags->{'SS'}) * 1000);
	$tags->{'TIME'}	    = sprintf "%.2d:%.2d", @{$tags}{'MM', 'SS'};

	close(FILE); return $tags;
}

##########
##########
# We now try to be clever, modifying the existing configuration files if
# possible.

sub AddTypes
{
  my $file;
  my $abc;
  
  if (!-e "../slimserver.pl")
  { die "I don't know what you're doing. Copy this file to Plugins. Then try this again, from there\n"; }
  
  print "Attempting to add types to custom.conf\n";
  
  $file = "";
  if (open (IN, "< ../custom-types.conf"))
  {
    # The file exists; we need to read and extract the bits we have
    # so that we can update the file with our new support
    while (<IN>)
    { 
      $file .= $_; # Process $_ if necessary
    } # get the lot
    $file =~ s/\n# abc bits\n(.*)# abc end\n/\n# abc bits\n/s;
  }
  
  if ($file !~ /\n# abc bits\n/)
  { $file .= "\n# abc bits\n"; }
  
  $abc =<<EOM;
abc     abc             text/vnd.abc            audio
EOM
  $file =~ s/\n# abc bits\n/\n# abc bits\n$abc# abc end\n/s;
  open(OUT, "> ../custom-types.conf") || die "Couldn't update custom-types.conf\n";
  print OUT $file;
  close(OUT);
  
  
  
  ########
  # Now we do the same thing with slimserver-convert.conf
  print "Attempting to add types to slimserver-convert.conf\n";
  
  $file = "";
  if (open (IN, "< ../slimserver-convert.conf"))
  {
    # The file exists; we need to read and extract the bits we have
    # so that we can update the file with our new support
    while (<IN>)
    { 
      $file .= $_; # Process $_ if necessary
    } # get the lot
    $file =~ s/\n# abc bits\n(.*)# abc end\n/\n# abc bits\n/s;
  }
  
  if ($file !~ /\n# abc bits\n/)
  { $file .= "\n# abc bits\n"; }
  
  $abc =<<EOM;
abc mp3 * *
        [sq_abc2midi.pl] \$FILE\$ | [timidity] -idqq -EFresamp=1 -OrSs1lx -o - - | lame --quiet -f -r - -
abc wav * *
        [sq_abc2midi.pl] \$FILE\$ | [timidity] -idqq -EFresamp=1 -Ow -o - -
EOM
  $file =~ s/\n# abc bits\n/\n# abc bits\n$abc# abc end\n/s;
  open(OUT, "> ../slimserver-convert.conf") || die "Couldn't update slimserver-convert.conf\n";
  print OUT $file;
  close(OUT);
  

  # Now create sq_abc2midi.pl - a tool for converting to a midi file on 
  # stdout as abc2midi doesn't support that.
  print "Creating sq_abc2midi.pl\n";
  open(OUT, "> ../Bin/sq_abc2midi.pl") || die "Cannot write sq_abc2midi.pl\n";
  print OUT <<EOM;
#!/usr/bin/perl
\$file = shift || die "Syntax: sq_abc2midi.pl <file>\n";

print STDERR "ABC2MIDI: \$file\n";

\$tmpname = "/tmp/sqabc.\$\$.mid";

\$output = `abc2midi \$file -o \$tmpname`;
print STDERR \$output;

open(IN, "< \$tmpname") || die;

while (<IN>)
{
  print;
}
close(IN);
unlink \$tmpname;
EOM
  close(OUT);
  chmod 0755, "../Bin/sq_abc2midi.pl"; 
  print "\nFiles updated.\n";
  print "\nYou will need to restart the server for this plugin to take effect.\n";
}

1;

__DATA__

PLUGIN_ABC
	EN	ABC to MIDI file converter

ABC
	EN	ABC sound file
