/utunes.pl
use strict;
use POSIX qw(:signal_h);
my $player = 'mplayer';
my $uthome = $ENV{ } . '/.utunes';
if (! -e $uthome) {
mkdir $uthome;
}
$SIG{ } = sub { };
my $playpid = 0;
{
my $file = shift;
my $finish = 1;
$SIG{ } = sub {
kill SIGTERM, $playpid;
$finish = 0;
};
$playpid = fork();
if ($playpid) {
my $r = 0;
while ($r != $playpid) {
$r = waitpid $playpid, 0;
print STDERR "waitpid returned $r";
}
$playpid = 0;
} else {
print $file;
exec $player,$file;
die "Could not exec $player";
}
return $finish;
}
{
if (-e "$uthome/pid") {
open PID, "$uthome/pid";
my $pid = <PID>; chomp $pid;
close PID;
print "Daemon already running on pid $pid\n";
return;
}
my $pid = fork();
if ($pid) {
open PID, ">$uthome/pid";
print PID "$pid\n";
close PID;
return;
}
open STDIN, '/dev/null';
open STDOUT, '>/dev/null';
#open STDOUT, ">>$uthome/error.log";
open STDERR, ">>$uthome/error.log";
my @list = ();
my $c;
{
if (-e "$uthome/current") {
open CURRENT, "$uthome/current";
$_ = <CURRENT> or $_ = '0';
close CURRENT;
/^(\d+)/;
$c = $1;
} else {
$c = 0;
}
if (-e "$uthome/playlist") {
@list = ();
open PLAYLIST, "$uthome/playlist";
while (<PLAYLIST>) {
chomp;
push(@list, $_);
}
close PLAYLIST;
}
}
reload();
$SIG{ } = \&reload;
{
kill SIGTERM, $playpid if $playpid;
unlink "$uthome/pid";
exit 0;
}
$SIG{ } = \&ohnoes;
while ($c <= $#list) {
open CURRENT, ">$uthome/current";
print CURRENT "$c $list[$c]\n";
close CURRENT;
if (play($list[$c])) {
$c++;
}
}
unlink "$uthome/current";
ohnoes();
}
{
my $path = shift;
return $path if m'^/';
my $pwd;
chomp ($pwd = `pwd`);
return "$pwd/$path";
}
my $cmd = shift;
my $pid;
if (-e "$uthome/pid") {
open PID, "$uthome/pid";
$pid = <PID>; chomp $pid;
close PID;
}
my $current;
if (-e "$uthome/current") {
open CURRENT, "$uthome/current";
$current = <CURRENT>; chomp $current;
close CURRENT;
}
{
return unless $pid;
kill SIGUSR1, $pid;
}
{
return unless $pid;
kill SIGUSR2, $pid;
}
if (not defined $cmd) {
if (-e "$uthome/current") {
$current =~ s/^\d+ //;
print "$current\n";
} else {
print "No song currently playing.\n";
}
} elsif ($cmd eq 'add' or $cmd eq 'load') {
if ($cmd eq 'add') {
open PLAYLIST, ">>$uthome/playlist";
} else {
unlink "$uthome/current";
open PLAYLIST, ">$uthome/playlist";
}
if (@ARGV) {
print PLAYLIST fullpath($_) . "\n" foreach @ARGV;
} else {
print PLAYLIST while <STDIN>;
}
updatelist();
} elsif ($cmd eq 'rm' or $cmd eq 'del') {
open PLAYLIST, "$uthome/playlist";
open PLAYLISTOUT, ">$uthome/playlist.newtmp";
my @deletes;
if (!@ARGV) {
while (<STDIN>) {
chomp;
push @deletes, $_;
}
} else {
@deletes = @ARGV;
}
while (my $file = <PLAYLIST>) {
chomp $file;
print PLAYLISTOUT "$file\n" unless grep { $_ eq $file } @deletes;
}
close PLAYLISTOUT;
close PLAYLIST;
rename "$uthome/playlist.newtmp", "$uthome/playlist";
updatelist();
} elsif ($cmd eq 'clear') {
open PLAYLIST, ">$uthome/playlist";
close PLAYLIST;
unlink "$uthome/current";
updatelist();
} elsif ($cmd eq 'list') {
open PLAYLIST, "$uthome/playlist";
print while <PLAYLIST>;
close PLAYLIST;
} elsif ($cmd eq 'play') {
if ($pid) {
print "Already playing.\n";
} else {
daemon();
}
} elsif ($cmd eq 'next') {
$current++;
open CURRENT, ">$uthome/current";
print CURRENT "$current\n";
close CURRENT;
updatelist();
hurk();
} elsif ($cmd eq 'prev') {
$current--;
open CURRENT, ">$uthome/current";
print CURRENT "$current\n";
close CURRENT;
updatelist();
hurk();
} elsif ($cmd eq 'stop') {
kill SIGTERM, $pid if $pid;
} elsif ($cmd =~ /-?h(elp)?/) {
print <<EOD
utunes - a music player for UNIX hackers
usage: utunes [command] [files]
Commands are one of the following:
play begin playing the current playlist
stop stop playing the current playlist
next skip to the next song
prev skip to the previous song
add append files from the command line or stdin to the playlist
load replace the current playlist with files from stdin or command
line
rm delete files from the command line or stdin from the
playlist
del alias for rm
clear clear the current playlist
list dump the current playlist to stdout
If utunes is run without a command, the currently playing song is
printed to stdout.
EOD
}