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

Hey. I'm trying to write a daemon frontend for Audio::Play::MPG123. So far things are going decently well, but I've ran into a few problems that may be bugs somewhere. 1) I'm continously testing state() to be 0 so I can load the next song in the queue. It works fine for when a song ends naturally. But when I call the stop() method, it doesn't seem to change the state to 0. How can I make the state() be 0? What modifications should I make? 2) Sometimes stop() doesn't seem to even stop the player! I think this is a bug in the actual mpg123 player itself: I compiled the one included in the distribution with 'make linux-esd && make install'. Esd is running when these bugs occur. They also occur without esd running. 3) If I start the player with 2 songs, the 2nd song correctly plays when the first finishes. If I start with 1 song, then add the 2nd, it ends up in the queue (I check.) but when the 1st song finishes, the script exits. (See the forked while loop.) For some reason the song isn't in the queue outside of the 'until $self->{player}->state == 0' bit! The module code:
package Audio::MP3::JMD; # Ewww! use Audio::Play::MPG123; use strict; use warnings; sub new { my $class = shift; my $args = shift; my @songs = @{$args->{songs}}; my $code = $args->{code}; my $self = { player => new Audio::Play::MPG123, queue => [@songs], pointer => 0, code => $code }; bless $self, $class; $self->{player}->load($self->{queue}->[$self->{pointer}]); $self->{player}->statfreq(1.0/$self->{player}->tpf); unless (fork()) { while (1) { until ($self->{player}->state == 0) { $self->{player}->poll(1); $self->{code}->($self->{player}); } $self->{pointer}++; unless ($self->{queue}->[$self->{pointer}]) { exit 1; } else { $self->{player}->load($self->{queue}->[$self->{pointer}]); } } } return $self; } sub add { my $self = shift; my @songs = @_; push @{$self->{queue}}, @songs; } sub next { my $self = shift; $self->{pointer}++; $self->stop() if $self->{pointer} > $#{$self->{queue}}; $self->{player}->load($self->{queue}->[$self->{pointer}]); } sub prev { my $self = shift; $self->{pointer}--; $self->stop() if ( $self->{pointer} < 0 ); $self->{player}->load($self->{queue}->[$self->{pointer}]); } sub pause { my $self = shift; $self->{player}->pause() unless $self->{player}->paused(); } sub resume { my $self = shift; $self->{player}->pause() if $self->{player}->paused(); } sub toggle { my $self = shift; $self->{player}->pause(); } sub restart { my $self = shift; $self->{player}->jump(0); } sub forward { my $self = shift; my $seconds = shift; $self->{player}->jump("+$seconds"); } sub backward { my $self = shift; my $seconds = shift; $self->{player}->jump("-$seconds"); } sub stop { print "STOP\n\n\n"; my $self = shift; $self->{player}->stop(); # The forked while loop doesn't catch this! # A brief note about exiting: When the user (program that uses this m +odule) # calls this method, stop(), or when the forked process that handles +the queue # reaches the end, the forked process will exit, as will the mpg123 p +rocess. # The user will then get a CHLD signal, which they will _HAVE TO HAND +LE_! } 1; __END__
An example script:
#!/usr/bin/perl use Audio::MP3::JMD; use POSIX ":sys_wait_h"; $| = 1; my $player = new Audio::MP3::JMD ({ songs => ["/root/electronica/metro +idmodules.mp3"], code => sub { return; } }); $player->add("/root/electronica/fleetingecstacy.mp3"); $SIG{CHLD} = sub { my $stiff; while (($stiff = waitpid(-1, &WNOHANG)) > 0) { print "Nighty, night!\n"; print $stiff, "\n"; exit 1; } }; do { print join "\n", @{$player->{queue}}; print "\n"; print "-" x 80; sleep 5; } while 1;
I've emailed the author of A::P::M, no reply yet. Any advice is welcome. Sorry about the formatting; I'm in E-Links. Any more details needed? Reply here or contact me on irc.freenode.net, channel #perl, alias dabreegster.

Janitored by holli - added readmore-tag

Replies are listed 'Best First'.
Re: Music queue bugs
by northwind (Hermit) on May 26, 2005 at 20:40 UTC

    This in no way answers your question nor am I certain that this response applies in this situation, but...  you do realize there are copyright issues involved with using MP3 technology; these copyright issues are the reason why XMMS no longer supports MP3 (as of at least version 1.2.x).  An open source solution is to switch to Ogg Vorbis format, though the option of switching formats has issues all its own.

      This is getting way off-topic here, but I just want to correct a slight misstatement there: XMMS supports MP3 just fine. It's RedHat that doesn't: http://www.redhat.com/advice/speaks_80mm.html. My brand new gentoo installation of xmms plays mp3's just fine ;-) Even my RHEL3AS machine plays mp3's once I downloaded the source and recompiled it.

        Personally, I don't feel that using mp3s is morally wrong or wrong in a free software sense. I use mpg321, which is Free. Most of my songs are either ripped off CDs that I legally purchased or remixes of songs from videogames. (ocremix.org and vgmix.com) But regardless, ogg isn't commonplace yet and mp3s seem to have better quality, though I don't know much about the ogg format. In any case, I will still continue to work on my mp3 player. I'm still welcome to suggestions about this code, but I've decided to go a bit deeper. See my other node in Seekers of Perl Wisdom for further information.