#! /usr/bin/perl

# Quick hack to make an .M3U for a directory full of .ogg files.
# Reads all the .ogg files and then produces an M3U for them.
# Always uses the current directory, and writes a <cwd.m3u> file.
# If that file exists, aborts.  If there are no oggs, writes no file.
# If you want recursion... use find.

use strict;
use warnings;

use File::Glob ':glob';
use Date::Manip;

our $OGGINFO = '/usr/local/bin/ogginfo';

my $cwdname = `pwd`;
chomp $cwdname;
if($cwdname =~ /([^\/]*)$/)
{
	$cwdname = $1;
}
if(-e "$cwdname.m3u")
{
	warn "File $cwdname.m3u exists; not processing.";
	exit 0;
}

my @files = bsd_glob('./*.ogg', GLOB_NOSORT|GLOB_ERR);
if(GLOB_ERROR)
{
	die "Can't read directory: $!";
}

unless(@files)
{
	warn "No .ogg files; not processing.";
	exit 0;
}

my @refs = ();
foreach my $file (@files)
{
	push @refs, getfileinfo($file);
}

@refs = sort trackorder @refs;

open(OUTFL, ">$cwdname.m3u") or die "Can't write $cwdname.m3u: $!";
print OUTFL "#EXTM3U\n";
foreach my $ref (@refs)
{

	if($ref->{artist})
	{
		print OUTFL "#EXTINF:$ref->{length},$ref->{artist} - $ref->{title}\n";
	}
	else
	{
		print OUTFL "#EXTINF:$ref->{length},$ref->{title}\n";
	}
	print OUTFL "$ref->{filename}\n";
}

# Sort function to put items in track order.
sub trackorder
{
	# First, sort by album name.
	if ($a->{album} ne $b->{album})
	{
		return $a->{album} cmp $b->{album};
	}

	# Then, sort by track number.
	return $a->{tracknumber} <=> $b->{tracknumber};
}

# use oggenc to get some file info, and return a reference to that info.
sub getfileinfo
{
	my $filename = shift;

	my @lines = `$OGGINFO $filename`;
	chomp @lines;

	my %info = ();
	$info{filename} = $filename;
	foreach my $line (@lines)
	{
		if($line =~ /\s+(title|artist|genre|album|tracknumber)=(.*)/)
		{
			$info{$1} = $2;
		}
		if($line =~ /\s+Playback length: (.*)/)
		{
			$info{length} = toseconds($1);
		}
	}

	return \%info;
}

# Given a duration in m:s format, make it seconds.
sub toseconds
{
	my $elapsed = shift;
	$elapsed =~ s/:/ /g;
	$elapsed =~ s/m /mn /g;
	my $delta = ParseDateDelta($elapsed);
	my $seconds = Delta_Format($delta,0,'%st');
	$seconds = sprintf("%0.0d", $seconds);
	return $seconds;
}
