/upod.pl
use File::Basename;
use File::Copy;
use Getopt::Long;
use strict;
my $uthome = $ENV{ } . '/.utunes';
my $outdir = $ENV{ } . "/dspod";
my $name = "playlist";
my ($size, $time);
my $proc;
$proc = sub {
my ($in, $out) = @_;
$in =~ s/"/\\"/g;
$out =~ s/\.\w+$/.ogg/;
$out =~ s/"/\\"/g;
system(qq!conv -f ~/dspod/Convfile -o "$out" "$in"!);
return $out;
};
GetOptions(
"outdir=s" => \$outdir,
"size=s" => \$size,
"time=s" => \$time,
"name=s" => \$name,
);
{
my ($s, $m, $h) = reverse split(/:/, shift);
return $h * 3600 + $m * 60 + $s;
}
{
my $filename = shift;
my $length;
$filename =~ s/"/\\"/g;
open UDB, qq!udb info "$filename"|!;
while (<UDB>) {
if (/length\s+(.*)$/) {
$length = timeparse($1);
last;
}
}
close UDB;
return $length;
}
mkdir $outdir unless -d $outdir;
if ($size) {
if ($size =~ /[Kk]$/) {
$size *= 10**3;
} elsif ($size =~ /[Mm]$/) {
$size *= 10**6;
} elsif ($size =~ /[Gg]$/) {
$size *= 10**9;
} elsif ($size =~ /[Tt]$/) {
$size *= 10**12;
}
}
if ($time) {
$time = timeparse($time);
}
my @files;
open FILES, $ARGV[0] || "$ENV{HOME}/.utunes/playlist";
chomp(@files = <FILES>);
close FILES;
my $n = 0;
my ($c, $t);
my $residual; # The residual is a processed file from the previous iteration
# and is copied instead of reprocessed.
LIST: {
$c = 0;
$t = 0;
my ($dir, $playlist);
if ($size || $time) {
$dir = "$outdir/${name}_$n";
$playlist = "$outdir/${name}_$n/${name}_$n.m3u";
} else {
$dir = "$outdir/$name";
$playlist = "$outdir/$name/$name.m3u";
}
mkdir $dir unless -d $dir;
open PLAYLIST, ">$playlist";
print PLAYLIST "# Generated by upod\n";
my $i = 0;
while (@files) {
my $file = shift @files;
my $length = songlength($file);
next if $time && $length > $time;
my $outfile = $dir . '/' . sprintf("%04d_", $i) . basename $file;
print PLAYLIST "$outfile\n";
die "$outfile already exists!" if -e $outfile;
if ($proc) {
if ($residual) {
# If the residual has been processed,
# its new $outfile will have the wrong
# extension
$residual =~ /(\.\w+)$/;
my $residual_extension = $1;
$outfile =~ s/\.\w+$/$residual_extension/;
move $residual, $outfile;
undef $residual;
} else {
# Process the file somehow
$outfile = &$proc($file, $outfile);
}
} else {
symlink $file, $outfile
or copy $file, $outfile
or die "Could not symlink or copy $file to $outfile";
}
if ($size && -s $outfile > $size) {
unlink $outfile;
next;
}
# The size of a file will change if it is processed, but
# (unless something screwy is going on) the length will not.
if (($size && $c + -s $outfile > $size) ||
($time && $t + $length > $time)) {
$n++;
unshift @files, $file;
if ($proc) {
$residual = $outfile;
}
print PLAYLIST "# $c bytes, $t seconds\n";
close PLAYLIST; # I don't strictly have to close the
# file (it is automatically closed when
# PLAYLIST is reopened above), but if I
# don't some hapless C programmer will
# come across this and freak out.
goto LIST;
}
$c += -s $outfile;
$t += $length;
} continue {
$i++;
}
}
print PLAYLIST "# $c bytes, $t seconds\n";
close PLAYLIST;