#!/usr/bin/perl -w
use strict;

# jukebox - http://raf.org/jukebox/
#
# Copyright (C) 2002 raf <raf@raf.org>
#
# 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
# or visit http://www.gnu.org/copyleft/gpl.html

# jukebox - play selected music continuously in random order
#
# 20021208 raf <raf@raf.org>

# Set defaults and load configuration

my ($name) = $0 =~ /([^\/]+)$/;
my $default_root = '/mnt/music';
my $default_tocglob = '00*.toc';
my $default_gap = 2;
my $default_player = 'wav=play,mp3=mpg321 -q,ogg=ogg123 -q,flac=flac -sdc % | play -t wav -';
my $default_opts = 'short';

load('/etc/jukebox.conf');
load("$ENV{HOME}/.jukeboxrc");

sub help
{
	print << "ENDHELP";
NAME

$name - play selected music continuously in random order

SYNOPSIS

  $name [options] [--] [selector...]
  options:
    -h, --help            - Show the help message then exit
    -V, --version         - Show the version message then exit
    -d, --debug           - Print debug messages
    -a, --all             - Select everything (not just your favourites)
    -j, --strict          - Search for selectors only in "Jukebox" tags
    -m, --mandatory       - Search treating all selectors as mandatory
    -n, --list            - Just list matching tracks (don't play them)
    -x, --extra           - Show artist/album/title as well (implies -n)
    -e, --elide           - Suppress duplicate artist/albums (implies -x)
    -v, --withtags        - Include tags when listing tracks (implies -x)
    -s, --sequential      - Play tracks sequentially, then stop
    -c, --continuous      - Play continuously (even if -s)
    -i, --nouser          - No user interaction between tracks
    -g, --gap seconds     - Inter track gap (in seconds)
    -f, --playlist file   - Play tracks from a playlist file
    -r, --root dir[:dir]* - Override default music directory ($default_root)
    -t, --tocglob tocglob - Override default tocfile glob ($default_tocglob)
    -p, --player player   - Override default music players ($default_player)
    -u, --unlink          - Unlink playlist (see -f) after reading it
    -T, --tagstats        - List known selectors/categories/tags
    -P, --perl            - Perl junkie (perl re in search criteria)

DESCRIPTION

$name plays selected music continuously in a random order.
By default, $name only plays your favourite tracks (see below).
If the -a option is supplied, any tracks might be played.

If selectors are supplied, $name plays matching tracks.
For a track to match, it must:

  - match all of the selectors that start with '+',
  - match none of the selectors that start with '-', and
  - match at least one of the ordinary selectors.

Searches are case and accent insensitive. Phrases can be
quoted with single or double quotes (courtesy of the shell).

$name searches tocfiles for selectors in:

  - "Artist:", "Title:" and "Jukebox:" (and any other) headers,
  - track titles, and
  - track specific "[Jukebox: ...]" tags.

Your favourite tracks are defined to be those that are tagged
with your login name. The default selector is your login name.

The -j option causes $name to ignore artist names and album and
track titles. The search for selectors only looks at "Jukebox:"
headers and track specific "Jukebox:" tags. This searches for
tracks by category rather than by name.

The -m option causes all selectors to be treated as mandatory.
This has the same effect as adding a '+' character to the
start of every selector that does not already start with a '+'
or '-' character.

The -f option plays tracks listed in a playlist file rather than
using selectors to search for tracks. The format of the playlist
is one filename per line (just like the output of the -n option).
The -u option causes this file to be deleted after it is read.

The -s option plays the selected tracks in order, and then stops.
This can be used to play a single album. If only a single track
is selected, then the -s option is assumed. Adding the -c option
repeats the in order selection continuously rather than stopping.
This can be used to drive the neighbours mad while you're on holiday.

After each track is played, the user is asked whether or not they
wish to continue. If there is no answer within two seconds, jukebox
continues with the next track. If the user enters 'n' quickly enough,
jukebox will terminate. The -i option causes this interaction to be
suppressed, so jukebox will continue until it is killed by external
means. The -g option causes a pause between tracks.

The -n option just prints the selected tracks without playing them.
The -x option adds the artist, album and track titles to this output.
The -e option suppresses duplicate artists and album titles from this
output (the fields are present but empty). This reduces network traffic.
The -v option adds a field containing each track's jukebox tags. This is
to aid remote robot clients that need more information for compiling
playlists. The -e and -v options imply the -x option and the -x option
implies the -n option.

The -t, -r and -p options override various default values.
The argument to the -r option can contain a colon separated list
of directories to select tracks from multiple places.

The -P option allows perl "regular expressions" in the search criteria.

The -T option lists all categories used in all tocfiles (after the
"Jukebox:" header or in track specific "[Jukebox: ...]" tags). After
each category there are four numbers:

  - the number of albums that match the category,
  - the number of individual tracks that explicitly match the category,
  - the total number of tracks that match (inherited or explicit), and
  - the number of selected tracks that match the criteria.

Here's an example set of jukebox tags but feel free to classify tracks
however you see fit.

  rock rockabilly glam punk black metal thrash surf garage pub grunge seattle
  jazz ragtime bebop bigband swing boogiewoogie dixieland free acid funk jive
  blues delta stlouis louisiana chicago downhome gutbucket stomp prewar dirty
  reggae ska dub ragamuffin rap gansta pranks
  techno rave hiphop triphop trance club house dance eurotechno eurohouse
  eurodance tribal urban gogo gabber hi-nrg newbeat freestyle anime gfunk
  industrial breakbeat hardcore drill grindcore ghettotech biphop idm
  country western bluegrass americana texmex christian rodeo yodeling square
  honkytonk bakersfield outlaw queercore riotgrrl doowop
  pop britpop boyband girlband rnb bubblegum jpop synthpop skiffle anti twee
  alternative indie newage newwave darkwave fusion crossover nova gothic
  classical symphonies operas operettas arias cantatas fugues canons
  concertos chamber sonatas musique-concrete divas counter tenors oratorios
  madrigals motets serenades preludes waltzes ballet suites
  folk shanties filk ballad torchsong gospel ccm
  avantgarde primus booty chanson jam terror negerpunk polskpunk
  space cult psychedelic madchester shoegazing
  disco soul motown muzak crooners lounge barbershop karaoke
  childrens nursery rhymes lullabies holiday
  military march tattoo ballroom

  world european african asian indian australian pacific american
  usa english british canadian oz aboriginal celtic irish welsh
  french spanish portuguese italian german tibetan chinese japanese
  hawaiian cajun latin carribean andean brazillian cuban arabic
  egyptian pakistani hindustani continental goa algerian tuvan gypsy
  armenian azerbaijani greek iranian iraqi israeli kurdistani kyrgyztani
  lebanese turkish

  bossanova calypso candombe carnatic chacha conjunto corrido fado
  flamenco junkanoo mariachi merengue norteno ranchero rhumba salsa
  samba tango tejano vallenato zydeco taiko afrobeat afropop hi-life
  mquanga juju soukous township qawwali rai polka rebetiko gamelan
  zarzeula klezmer chazzanut

  male female vocal instrumental spoken poetry acappella chant choral
  acoustic electric electronic power ambient microtonal noise fractal

  tv radio movie theatre showtunes dancehall musical cabaret
  vaudeville broadway soundtracks themes

  string guitar piano brass woodwind drum bass percussion

  gregorian medieval romantic renaissance baroque contemporary
  traditional modern early late recent new progressive
  neo mod post retro revival

  solo duet trio quartet band choir orchestra

  north south east west central

  live studio

  20s 30s 40s 50s 60s 70s 80s 90s 00s

  awesome excellent good fair bad crap weird

  comedy novelty happy depressing disturbing death relaxing

  political protest class gender race war peace

  hard soft easy loud quiet fast slow hot cool smooth explicit

  driving cooking gardening meditating housework washingup party

SIGNALS

When jukebox receives a SIGTERM signal, it sends a SIGTERM signal to any
player processes and then exits. This stops the jukebox.

When jukebox receives a SIGUSR1 signal, it sends a SIGSTOP or SIGCONT signal
to any player processes. This pauses and continues the current track.

When jukebox receives a SIGUSR2 signal, it sends a SIGTERM signal to any
player processes. This skips to the next track.

EXAMPLES

Play your favourite tracks

  jukebox

List your favourite tracks

  jukebox -n

Create a playlist file of Eric Clapton tracks

  jukebox -n 'eric clapton' > eric.play

Play tracks from a playlist file

  jukebox -f - < eric.play

List all known tags and a histogram of their use

  jukebox -T -a

Play a single album in order, then stop

  jukebox -s +"janis joplin" +'cheap thrills'

Play a single song over and over and over again

  jukebox -c 'night and day'

Play female jazz singers of the 1940's (two versions)

  jukebox -j +female +vocal +jazz +40s
  jukebox -jm female vocal jazz 40s

Play anything but the Wiggles

  jukebox -- -wiggles

NOTE

If there is a jukebox network server running, then it is impolite to use
jukebox directly. Use jukeboxc (in command line or graphical mode) instead.

NOTE

The long options are only available if the value of the juke_opts variable
in /etc/jukebox.conf is "long". This is because the standard perl module,
Getopt::Long, requires the presence of a "--" argument before any arguments
that begin with "+" because it thinks they are options (unless
\$POSIXLY_CORRECT is set in the environment). Since it is expected that this
program will receive many command line arguments that begin with "+", the
default is to only handle single letter options via the Getopt::Std module.
Note that, with either short or long options, "--" must be used whenever
there are search terms that begin with "-" because these really do look like
options.

FILES

  /etc/jukebox.conf - System wide configuration file
  ~/.jukeboxrc      - User specific configuration file

SEE ALSO

  rip(1), riptrack(1), mktoc(1), toc2names(1), toc2tags(1),
  cdr(1), cdrw(1), burn(1), burnw(1), cdbackup(1), mp3backup(1),
  jukebox(1), jukeboxc(1), jukeboxc.jar(1), jukeboxd(8),
  jukeboxd-init.d(8), jukebox.conf(5),
  http://raf.org/jukebox/Jukebox-HOWTO

AUTHOR

raf <raf\@raf.org>

ENDHELP

	exit;
}

sub version()
{
	print "jukebox-0.1\n";
	exit;
}

# Check the arguments

my %opt;
help() unless do_opts();
help() if exists $opt{h};
version() if exists $opt{V};
my $debug = exists $opt{d};
my $all = exists $opt{a};
my $strict = exists $opt{j};
my $mandatory = exists $opt{m};
my $withtags = exists $opt{v};
my $elide = exists $opt{e};
my $extra = exists $opt{x} || $elide || $withtags;
my $list = exists $opt{n} || $extra;
my $seq = exists $opt{s};
my $cont = exists $opt{c};
my $user = !exists $opt{i};
my $gap = $opt{g} || 0;
my $playlist = $opt{f} if exists $opt{f};
my (@root) = split /[,: ]+/, $opt{r} || $default_root;
my $tocglob = $opt{t} || $default_tocglob;
my %player = decode_player($opt{p} || $default_player);
my $unlink = exists $opt{u};
my $tagstats = exists $opt{T};
my $perl = exists $opt{P};
my (@all, @none, @any);
my @states = (SIGSTOP(), SIGCONT());
my $state = 0;

die "Abort: Selectors and the -a option are mutually exclusive.\n" if $all && $#ARGV != -1;
die "Abort: Selectors and the -f option are mutually exclusive.\n" if defined $playlist && $#ARGV != -1;
die "Abort: The -a and -j options are mutually exclusive.\n" if $all && $strict;
die "Abort: The -a and -m options are mutually exclusive.\n" if $all && $mandatory;
die "Abort: The -a and -f options are mutually exclusive.\n" if $all && defined $playlist;
die "Abort: The -f and -j options are mutually exclusive.\n" if defined $playlist && $strict;
die "Abort: The -f and -m options are mutually exclusive.\n" if defined $playlist && $mandatory;
die "Abort: The -f and -nxev options are mutually exclusive.\n" if defined $playlist && $list;
die "Abort: The -f and -T options are mutually exclusive.\n" if defined $playlist && $tagstats;
die "Abort: The -g option's argument must be numeric.\n" unless $gap =~ /^[\d.]+$/;
die "Abort: The -f option's argument must be \"-\" or a filename.\n" if defined $playlist && $playlist ne '-' && ! -f $playlist;
die "Abort: The -r option's argument (or juke_root) must contain at least one directory.\n" if $#root == -1;
die "Abort: The -p option's argument (or juke_player) must contain at least one player.\n" if $#{[keys %player]} == -1;
die "Abort: The -u option requires the -f option.\n" if $unlink && !defined $playlist;
die "Abort: The -T and -nxev options are mutually exclusive.\n" if $tagstats && $list;

for (@root)
{
	die "Abort: The -r option's argument must contain only directories.\n" unless -d;
}

for (@ARGV)
{
	push(@all, $1), next if /^\+(.+)$/;
	push(@none, $1), next if /^-(.+)$/;
	push(@all, $_), next if $mandatory;
	push(@any, $_);
}

$_ = normalise($_, !$perl) for (@all);
$_ = normalise($_, !$perl) for (@none);
$_ = normalise($_, !$perl) for (@any);

my $any = qr/@{[join '|', @any]}/i if $#any != -1;
$any = qr/$ENV{LOGNAME}/i, $strict = 1 unless have_selectors() or $all or defined $playlist;

if ($debug)
{
	print "Options:\n";
	print "debug=$debug all=$all strict=$strict mandatory=$mandatory list=$list extra=$extra elide=$elide withtags=$withtags seq=$seq cont=$cont user=$user gap=$gap unlink=$unlink tagstats=$tagstats perl=$perl\n";
	print "playlist=", (defined $playlist) ? $playlist : '<none>', "\n";
	print "root=@root tocglob=$tocglob player=@{[encode_player(%player)]}\n";
	print "all: ", ($#all != -1) ? @all : '<none>', "\n";
	print "none: ", ($#none != -1) ? @none : '<none>', "\n";
	print "any: ", (defined $any) ? $any : '<none>', "\n";
	print "\n";
}

# Parse all toc files looking for suitable tracks

# Toc files are of the form:
#
# Artist: ............           # required - not really
# Title: .............           # required - not really
# Other: .............           # optional - tags here apply to all tracks
# Jukebox: tags                  # optional - tags here apply to all tracks
#                                # required blank line
# 01 Track Name [Jukebox: tags]
# 02 ...

my @toc;
my @tracks;
my @artists;
my @albums;
my @tags;
my @titles;
my %album_categories;
my %track_categories;
my %total_categories;
my %selected_categories;
my $num_albums = 0;
my $num_tracks = 0;

if (defined $playlist)
{
	open(PLAYLIST, $playlist) || die "Failed to open '$playlist' for reading: $!\n";

	while (<PLAYLIST>)
	{
		chop;
		next if /'/;
		next unless /\.(@{[join '|', keys %player]})$/i;
		next unless -f;
		push(@tracks, $_);
	}

	close(PLAYLIST);
	unlink($playlist) if $unlink && $playlist ne '-';
}
else
{
	push(@toc, split /\n/, `find "$_" -name '$tocglob'`) for (@root);

	for my $tocfile (sort @toc)
	{
		if (open(TOC, $tocfile))
		{
			my $tocpattern = $tocglob;
			$tocpattern =~ s/\*/.*/;
			my ($dir) = $tocfile =~ /^(.*\/)$tocpattern$/;
			++$num_albums if $tagstats;
			my $artist;
			my $album;
			my $title;

			# Artist, Title, etc. apply to all tracks.

			my $cd = '';
			my $jheader = undef;

			while (<TOC>)
			{
				last if /^$/;
				chop;

				if (/^([A-Za-z]+): (.*)$/)
				{
					$cd .= ' ' . $2;

					$artist = $2 if $list && $extra && $1 eq 'Artist';
					$album = $2 if $list && $extra && $1 eq 'Title';
					$jheader = (defined $jheader) ? "$jheader $2" : $2 if $1 eq 'Jukebox';

					if ($tagstats && $1 eq 'Jukebox')
					{
						++$album_categories{$_} for (split /[\s,]+/, $2);
					}
				}
			}

			# Gather tracks that match

			while (<TOC>)
			{
				chomp;
				next unless my ($index, $track) = $_ =~ /^(\d{2}) (.*)$/;
				my ($jtags) = $track =~ /\[[Jj]ukebox: ([^\]]+)\]/;
				my $search = ($strict) ? (defined $jheader ? $jheader : '') . (defined $jtags ? ' ' . $jtags : '') : $cd . ' ' . $track;
				++$num_tracks if $tagstats;

				if ($all || (have_selectors() && match_selectors($search)))
				{
					print "check: $search\n" if $debug;
					my @glob = grep { /\.(@{[join '|', keys %player]})$/i } glob("$dir$index*");
					next unless defined $glob[0];
					next unless $glob[0] =~ /\.(@{[join '|', keys %player]})$/i;
					next if $glob[0] =~ /'/;
					push(@tracks, $glob[0]);
					print "match: $glob[0]\n" if $debug;

					if ($list && $extra)
					{
						$track =~ s/\s*(\[[Jj]ukebox: [^\]]*\])\s*//;
						push(@artists, $artist);
						push(@albums, $album);
						push(@titles, $track);

						if ($withtags)
						{
							my $tags = $jheader if defined $jheader;
							$tags = (defined $tags) ? "$tags $jtags" : $jtags if defined $jtags;
							$tags =~ s/^\s+//;
							$tags =~ s/\s+$//;
							$tags =~ s/\s+/ /;
							push(@tags, $tags);
						}
					}

					if ($tagstats && defined $jtags)
					{
						++$selected_categories{$_} for (split /[\s,]+/, $jtags);
					}

					if ($tagstats && defined $jheader)
					{
						++$selected_categories{$_} for (split /[\s,]+/, $jheader);
					}
				}

				if ($tagstats && defined $jtags)
				{
					++$track_categories{$_}, ++$total_categories{$_} for (split /[\s,]+/, $jtags);
				}

				if ($tagstats && defined $jheader)
				{
					++$total_categories{$_} for (split /[\s,]+/, $jheader);
				}
			}

			close(TOC);
		}
	}
}

# Just list selected tracks?

if ($list)
{
	if ($extra)
	{
		for (my $i = 0; $i <= $#tracks; ++$i)
		{
			my $artist = ($elide && $i && $artists[$i] eq $artists[$i - 1]) ? '' : $artists[$i];
			my $album = ($elide && $i && $albums[$i] eq $albums[$i - 1]) ? '' : $albums[$i];
			my $tags = ($withtags) ? "\t" . $tags[$i] : '';
			print "$artist\t$album\t$titles[$i]\t$tracks[$i]$tags\n";
		}
	}
	else
	{
		print "$_\n" for (@tracks);
	}

	print "No matching tracks\n" if $#tracks == -1;
	exit;
}

# Just list known categories?

if ($tagstats)
{
	print "Categories      Albums Tracks Total  Selected\n";
	print "--------------- ------ ------ ------ --------\n";
	print sprintf("%-15s %6d %6d %6d %8d\n", $_, $album_categories{$_} || 0, $track_categories{$_} || 0, $total_categories{$_}, $selected_categories{$_} || 0) for (grep { $_ !~ /\b\d{4}\b/ } sort keys %total_categories);
	print "--------------- ------ ------ ------ --------\n";
	print sprintf("%-15s %6d %6d %6d %8d\n", 'Total', $num_albums, $num_tracks, $num_tracks, scalar @tracks);
	exit;
}

# Play selected music in random or sequential order

die "No matching tracks\n" if $#tracks == -1;

use POSIX;
my $last = $#tracks;
$seq = 1 if $#tracks == 0;
my $pid;
$| = 1;

$SIG{TERM} = \&term;
$SIG{USR1} = \&usr1;
$SIG{USR2} = \&usr2;
$SIG{INT} = 'IGNORE';

for (my $i = 0;; ++$i)
{
	$i = ($seq) ? (($i > $last) ? 0 : $i) : floor(rand($last + 1));
	print '[', $i + 1, '/', $last + 1, "] $tracks[$i]\n";
	# we need to sleep here otherwise the following errors can occur:
	# ogg123: Could not load default driver and no driver specified in config file. Exiting.
	# mpg321: Can't find a suitable libao driver. (Is device in use?)
	# maybe the sound device takes a while to get released.
	select(undef, undef, undef, $default_gap) if $default_gap && !$gap && $seq && !$i;
	select(undef, undef, undef, $gap) if $gap;
	my ($fmt) = $tracks[$i] =~ /\.(@{[join '|', keys %player]})$/i;
	die "Unknown format: '$tracks[$i]'\n" unless defined $fmt && defined $player{lc($fmt)};
	$tracks[$i] =~ s/%/%%/g;
	my $player = $player{lc($fmt)};
	$player .= ' %' unless $player =~ /(?<!%)%(?!%)/;
	$player =~ s/(?<!%)%(?!%)/'$tracks[$i]'/g;
	$player =~ s/%%/%/g;
	$pid = run_cmd($player);
	waitpid($pid, 0);
	$pid = undef;
	last if $i == $last && $seq && !$cont;

	if ($user)
	{
		print "Continue? ([y]/n): ";
		vec(my $rin = '', fileno(STDIN), 1) = 1;
		my $nfound = select(my $rout = $rin, undef, undef, 2);
		last if $nfound == 1 && <STDIN> =~ /[nN]/;
		print "\n";
	}
}

exit;

# Execute the player command

sub run_cmd
{
	my ($cmd) = @_;
	my $pid = fork;
	die "Failed to fork: $!\n" if $pid == -1;
	return $pid if $pid;
	print "exec $cmd\n" if $debug;
	setpgrp;
	exec $cmd;
	die "Failed to exec: $!\n";
}

# Handle SIGTERM (kill player process(es) if any, then exit)

sub term
{
	kill(-(SIGTERM), $pid) if defined $pid && $pid > 0;
	exit;
}

# Handle SIGUSR1 (pause/continue player process(es) if any)

sub usr1
{
	kill(-$states[$state], $pid), $state = !$state if defined $pid && $pid > 0;
}

# Handle SIGUSR2 (kill player process(es) but continue)

sub usr2
{
	kill(-(SIGTERM), $pid) if defined $pid && $pid > 0;
}

# Are there any selectors?

sub have_selectors
{
	return $#all != -1 || $#none != -1 || defined $any;
}

# Match a string against selectors

sub match_selectors
{
	my ($str) = @_;

	$str = normalise($str, 0);

	for my $all (@all)
	{
		return 0 unless ($strict) ? $str =~ /\b$all\b/i : $str =~ /$all/i;
	}

	for my $none (@none)
	{
		return 0 if ($strict) ? $str =~ /\b$none\b/i : $str =~ /$none/i;
	}

	return 1 unless defined $any;
	return ($strict) ? $str =~ /\b$any\b/ : $str =~ /$any/;
}

# Remove accents and disable simple regular expressions

sub normalise
{
	my ($str, $re) = @_;

	$str =~ tr/¿ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåçèéêëìíîïðñòóôõöøùúûüýþÿ/?AAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaceeeeiiiidnoooooouuuuypy/;
	$str =~ s/Æ/AE/g;
	$str =~ s/æ/ae/g;
	$str = quotemeta($str) if $re;

	return $str;
}

# Decode the juke_player variable

sub decode_player
{
	my ($spec) = @_;
	my %player;

	# If only a single player is given, assume mp3 format

	if ($spec =~ /^([^:=,]+)$/)
	{
		$player{mp3} = $1;
		return %player;
	}

	for my $player (split /,/, $spec)
	{
		$player{lc($1)} = $2 if $player =~ /^([^=:]+)[=:](.+)$/;
	}

	return %player;
}

# Encode the juke_player variable

sub encode_player
{
	my (%player) = @_;

	return join(',', map { "$_=$player{$_}" } sort keys %player);
}

# Locate a command in $PATH

sub locate
{
	my ($cmd) = @_;

	for (split /:/, $ENV{PATH})
	{
		return "$_/$cmd" if -x "$_/$cmd";
	}

	return undef;
}

# Load the configuration file

sub load
{
	my ($config) = @_;
	return unless -r $config;
	return unless open(CONFIG, $config);

	while (<CONFIG>)
	{
		s/#.*$//;
		s/^\s+//;
		s/\s+$//;
		s/\s+/ /g;
		next if /^$/;
		$default_root = $1 if /^juke_root=['"]?([^'"]+)['"]?$/;
		$default_tocglob = $1 if /^juke_toc=['"]?([^'"]+)['"]?$/;
		$default_gap = $1 if /^juke_gap=['"]?([^'"]+)['"]?$/;
		$default_player = $1 if /^juke_player=['"]?([^'"]+)['"]?$/;
		$default_opts = $1 if /^juke_opts=['"]?([^'"]+)['"]?$/;
	}

	close(CONFIG);
}

# Process the command line options

sub do_opts
{
	if ($default_opts eq 'long')
	{
		use Getopt::Long; #qw(:config gnu_getopt);
		Getopt::Long::Configure qw(no_getopt_compat permute bundling);
		GetOptions \%opt, qw(h|help V|version d|debug a|all j|strict m|mandatory n|list x|extra e|elide v|withtags s|sequential c|continuous i|nouser g|gap=f f|playlist=s r|root=s t|tocglob=s p|player=s u|unlink T|tagstats P|perl);
	}
	else
	{
		use Getopt::Std;
		getopts 'hVdajmnxevscig:f:r:t:p:uTP', \%opt;
	}
}

# vi:set ts=4 sw=4
