dabreegster has asked for the wisdom of the Perl Monks concerning the following question:

A while ago I posted some code for my script that manages multiple instances of an mp3 player and allows you to play some songs, pause them, play another set, and resume the first when the second is complete. I sent STOP and CONT signals to mpg321 itself and it was rather messy, so I decided to use Audio::Daemon::MPG123. Everything is going pretty well now. I compiled the modified mpg123 from source in Audio::Play::MPG123 using the esd output. I had to make a few small modifications to the ::Server so that at the end of stop() it'd call $player->stop_mpg123() so that the forked Server process and mpg123 instance would hopefully exit. It all works pretty well. Sometimes, though, I get weird errors about Bad arg length for Socket::unpack_sockaddr_in, length is 0, should be 16 at /usr/lib/perl/5.8/Socket.pm line 198. Other times, it just works. But now my main problem is when I do this: play SONGS pause 1st set play NEWSONGS stop 2nd set 2nd set exits, and the CHLD signal is received the 1st set is supposed to resume, and it does but occaisonally it'll pause() again after a second, as if Play() is called again. I have no clue why. Here's the code for my music server. I realized that this could be anything since I've modified the A::D::M code a bit, but I'd like a few hints.
#!/usr/bin/perl -w ######################## # Jigstar Music Daemon # ######################## use POSIX ":sys_wait_h"; use Audio::Daemon::MPG123::Server; use Audio::Daemon::MPG123::Client; use Config::Auto; our (@Queue, $Config, $PortCounter); $| = 1; mkdir "/tmp/jmd"; open LOCK, "/var/lock/jmd" and do { kill 0, <LOCK> and die "Error: JMD already running!"; }; open LOCK, ">/var/lock/jmd"; print LOCK $$; close LOCK; $Config = Config::Auto::parse("/etc/jmd"); if ($Config->{mixer} eq "esd") { # Start ESD } $SIG{ALRM} = sub { return unless -s "/tmp/jmd/input"; open INPUT, "/tmp/jmd/input"; chomp($Cmd = <INPUT>); close INPUT; Play($Cmd) if $Cmd =~ s/^play //; Add($Cmd) if $Cmd =~ s/^add //; Next() if $Cmd eq "next"; Prev() if $Cmd eq "prev"; Restart() if $Cmd eq "restart"; Forward() if $Cmd eq "forward"; Backward() if $Cmd eq "backward"; Pause() if $Cmd eq "pause"; Resume() if $Cmd eq "resume"; Toggle() if $Cmd eq "toggle"; Stop() if $Cmd eq "stop"; $SIG{QUIT}->() if $Cmd eq "quit"; }; $SIG{CHLD} = sub { my $Stiff; while (($Stiff = waitpid(-1, &WNOHANG)) > 0) { pop @Queue; sleep($Config->{lag}); Resume() if @Queue; } }; $SIG{QUIT} = sub { unlink "/var/lock/jmd"; # Blank files # Close all instances exit; }; $SIG{INT} = $SIG{QUIT}; sub Play { Pause() if @Queue; my $Port = 9100 + ++$PortCounter; my $Server = new Audio::Daemon::MPG123::Server (Port => $Port); my $Client = new Audio::Daemon::MPG123::Client (Server => "localhost" +, Port => $Port); push @Queue, { Server => $Server, Client => $Client }; $Queue[-1]->{Server}->mainloop() unless fork(); Add(shift); } sub Add { @Songs = split(/\s+/, shift); # Handle filenames with escapes. $Queue[-1]->{Client}->add(@Songs) if @Queue; } sub Next { $Queue[-1]->{Client}->next() if @Queue; } sub Prev { $Queue[-1]->{Client}->prev() if @Queue; } sub Restart { $Queue[-1]->{Client}->jump("0s") if @Queue; } sub Forward { $Queue[-1]->{Client}->jump("+" . $Config->{forward} . "s") if @Queue; } sub Backward { $Queue[-1]->{Client}->jump("-" . $Config->{backward} . "s") if @Queue +; } sub Pause { return unless @Queue; my $Status = $Queue[-1]->{Client}->status(); $Queue[-1]->{Client}->pause() if $Status->{state} == 2; } sub Resume { return unless @Queue; my $Status = $Queue[-1]->{Client}->status(); $Queue[-1]->{Client}->pause() if $Status->{state} == 1; } sub Toggle { $Queue[-1]->{Client}->pause() if @Queue; } sub Stop { } #open SONG, ">/tmp/jmd/song"; #open TIMES, ">/tmp/jmd/times"; #do { # if (@Queue) { # my $Status = $Queue[-1]->{Client}->status(); # print "1: [" . $#Queue + 1 . "] " . $Status->{url} . do { " (P)" if + $Status->{state} == 1; }; # print "\n"; # my @Times = split(/,/, $Status->{frame}); # print "2: " . $Times[2] . "(" . $Times[3] . ")"; # print "\n"; # } # sleep 1; #} while 1; sleep while 1;

Replies are listed 'Best First'.
Re: Audio::Daemon::MPG123
by thcsoft (Monk) on May 09, 2005 at 07:19 UTC
    well, i don't exactly understand your code and its intentions, as i never worked with the modules you use. but what i'm tripping over in your question is the word "hopefully": "so that the forked Server process and mpg123 instance would hopefully exit."
    you didn't mention whether the errors can be reproduced. if they are not, but appear at random, then all that reminds me to some sort of a race condition. as if you are trying to communicate with a process, which may still be alive, but mustn't.

    language is a virus from outer space.
      I've got most of it working now. Now I'm looking for somebody else to help beta test it. Also, at the bottom of the code, I commented out the code to put the song name and frame time in a file because it was a bit buggy. If anybody could help me with it, I'd be grateful. I print the frametimes every second, but it stays the same. I'll post code later, but anybody with knowledge of this module could help.