#!/usr/bin/perl ################### # Title # # By Da-Breegster # ################### use strict; use warnings; use Audio::Daemon::MPG321; use Config::Auto; use MP3::Info; use POSIX ":sys_wait_h"; use List::Util "shuffle"; use Cwd; our (@Players, $MixerPID, %Config, $Title); $| = 1; mkdir "/tmp/jmd" unless -d "/tmp/jmd"; open LOCK, "/var/lock/jmd" and do { kill 0, and die "JMD already running!"; }; open LOCK, ">/var/lock/jmd"; print LOCK $$; close LOCK; %Config = %{Config::Auto::parse("/etc/jmd")}; do { do { $MixerPID = fork() or exec("esd -nobeeps"); system("echo $MixerPID >> /root/esd"); system("esdctl unlock"); } if system("esdctl standbymode >> /dev/null") == 256; } if $Config{mixer} eq "esd"; $SIG{ALRM} = sub { return unless -s "/tmp/jmd/input"; open INPUT, "/tmp/jmd/input"; chomp(my $Input = ); close INPUT; my ($Action, @Args); ($Action, @Args) = split(/\s+/, $Input); if ($Action eq "play" or $Action eq "add") { my @Songs = map { FullPath($_) } @Args; Play(@Songs) if $Action eq "play"; Add(@Songs) if $Action eq "add"; } elsif ($Action eq "rplay" or $Action eq "radd") { my @Songs = shuffle(@Args); @Songs = map { FullPath($_) } @Songs; Play(@Songs) if $Action eq "rplay"; Add(@Songs) if $Action eq "radd"; } else { Next() if $Action eq "next"; Prev() if $Action eq "prev"; Restart() if $Action eq "restart"; Forward(@Args) if $Action eq "forward"; Backward(@Args) if $Action eq "backward"; Pause() if $Action eq "pause"; Resume() if $Action eq "resume"; Toggle() if $Action eq "toggle"; Stop() if $Action eq "stop"; List() if $Action eq "ls"; $SIG{QUIT}->() if $Action eq "quit"; } }; $SIG{CHLD} = sub { my $Stiff; while (($Stiff = waitpid(-1, &WNOHANG)) > 0) { pop @Players; sleep($Config{lag}); Resume() if @Players; } }; $SIG{QUIT} = sub { unlink "/var/lock/jmd"; Stop() until (! @Players); kill "INT", $MixerPID if $MixerPID; open SONG, ">/tmp/jmd/song"; print SONG "[0]"; close SONG; open TIMES, ">/tmp/jmd/times"; print TIMES "0:00 (0:00)"; close TIMES; exit 0; }; $SIG{INT} = $SIG{QUIT}; sub FullPath { my $Song = shift; return $Song if $Song =~ m/^\//; my $CWD = getcwd; return "$CWD/$Song" if -f "$CWD/$Song"; return $Config{dir} . "/$Song" if -f $Config{dir} . "/$Song"; return; } sub Play { my @Songs = @_; Pause() if @Players; push @Players, new Audio::Daemon::MPG321 (@Songs); } sub Add { return unless @Players; $Players[-1]->add(@_); } sub Next { return unless @Players; $Players[-1]->next(); } sub Prev { return unless @Players; $Players[-1]->prev(); } sub Restart { return unless @Players; $Players[-1]->restart(); } sub Forward { return unless @Players; $Players[-1]->forward(shift); } sub Backward { return unless @Players; $Players[-1]->backward(shift); } sub Pause { return unless @Players; $Players[-1]->pause(); } sub Resume { return unless @Players; $Players[-1]->resume(); } sub Toggle { return unless @Players; $Players[-1]->toggle(); } sub Stop { return unless @Players; $Players[-1]->stop(); } sub List { open REPLY, ">/tmp/jmd/reply"; print REPLY "START\n"; foreach (@{$Players[-1]->{queue}}) { my $Prelude; if ($_ eq $Players[-1]->{queue}->[$Players[-1]->{pointer}]) { $Prelude = "> "; } else { $Prelude = " "; } print REPLY $Prelude . $_ . "\n"; } print REPLY "END\n"; close REPLY; } while (1) { select(undef, undef, undef, 0.5); next unless @Players; until ($Players[-1]->{player}->state() == 0) { $Players[-1]->{player}->poll(); if (my $Info = get_mp3tag($Players[-1]->{queue}->[$Players[-1]->{pointer}])) { $Title = $Info->{TITLE}; } else { $Title = $Players[-1]->{queue}->[$Players[-1]->{pointer}]; } open SONG, ">/tmp/jmd/song"; print SONG "[", $#Players + 1, "] ", $Title, "\n"; close SONG; open TIMES, ">/tmp/jmd/times"; print TIMES $Players[-1]->{player}->{sofar}, " (", $Players[-1]->{player}->{remains}, ")\n"; close TIMES; } $Players[-1]->{pointer}++; unless ($Players[-1]->{queue}->[$Players[-1]->{pointer}]) { Stop(); } else { $Players[-1]->load(); } }