#!/usr/bin/perl -w

## genm3u -- Update music collection playlists

## Created:    <Sun Apr 16 16:56:39 EST 2000>
## Time-stamp: <Wed Sep 20 17:50:55 EDT 2000>
## Author:     Alex Shinn <foof@eyeofdog.com>
## 
## Copyright (C) 2000 Eye of Dog, Inc.
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of
## the License, or (at your option) any later version.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public
## License along with this program; if not, write to the Free
## Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
## MA 02111-1307 USA


# Modules
use strict;
use Getopt::Long;

# Customizations
my $album_file = "album.m3u";
my $all_file = "all.m3u";
my $music_match = "\\.(mp[1-3]|ogg|wav)\$"; # what xmms understands

# Other Variables
my $version = 1.0;
my $updated = "Sun Sep 10 23:25:55 EDT 2000";
my %optctl;
my $root;

main();


# Main function

sub main {
  parse_opts();
  usage() if $optctl{"help"};
  version() if $optctl{"version"};
  write_all($root);
}


# Print a usage summary

sub usage {
  print <<EOF;
usage: $ARGV[0] [options] [directory]

  -h, --help               display this message
  -v, --version            print version info
EOF
  exit 0;
}


# Print version info

sub version {
  print "$ARGV[0] $version ($updated)\n";
  exit 0;
}


# Parse command line options

sub parse_opts {
  # Put all options into %optctl
  GetOptions(\%optctl, "h", "help", "v", "version") or usage();
  # Translate short options
  $optctl{"help"}     = $optctl{"h"} unless (exists $optctl{"help"});
  $optctl{"version"}  = $optctl{"v"} unless (exists $optctl{"version"});
  # Get the directory to work on
  $root = shift @ARGV;
  $root = `pwd` unless $root;
  $root =~ s{[/\n]*$}{};
}


# A filename given a relative directory path

sub dirfile {
  my $dir = shift;
  my $file = shift;
  return $dir ? "$dir/$file" : $file;
}


# Write the all.mp3 file for a directory

sub write_all {
  my $dir = shift || "";
  chdir $dir if $dir;
  my $is_album_dir = -e $album_file;
  my @files;

  # Get the file list
  foreach (glob("*")) {
    if (-d) {
      my @subdir_files = write_all($_);
      push(@files, @subdir_files);
      chdir "..";
    }
    elsif (/$music_match/o) {
      push @files, $_ unless $is_album_dir;
    }
  }

  # Write the all.m3u (unless it's an album dir)
  if ($is_album_dir) {
    # Get the album listing
    open(FILE, "< $album_file") or die "can't open $dir/$album_file: $!";
    my @album_files = <FILE>;
    close(FILE);
    # Adjust non-absolute file names
    foreach (@album_files) { chomp; s!^([^/].*)$!$1! };
    # Add the files to our list
    push(@files, @album_files);
  }
  elsif (@files) {
    open(FILE, "> $all_file") or die "can't open $dir/$all_file: $!";
    foreach (@files) {
      print FILE "$_\n";
    }
    close(FILE);
  }

  # Prepend the dir to the filenames
  foreach (@files) {
    $_ = dirfile($dir, $_);
  }

  # Return the files list
  return @files;
}

