#!/usr/bin/perl package Audio::Play::MPG321; use strict; use warnings; use IPC::Open2; use IO::Select; $| = 1; sub new { my $class = shift; my ($read, $write); my $pid = open2($read, $write, "mpg321", "--aggressive", "--skip-printing-frames=39", "-R", "start"); my $handle = IO::Select->new($read); my $self = { pid => $pid, read => $read, write => $write, handle => $handle, song => undef, sofar => "0:00", remains => "0:00", state => 2 }; bless($self, $class); return $self; } sub poll { my $self = shift; while ($self->{handle}->can_read(0.5)) { my $in; sysread($self->{read}, $in, 1024); $self->parse($in); } } sub parse { my $self = shift; my $in = shift; if ($in =~ m/^\@P /) { $in =~ s/^\@P //; $self->{state} = $in; } elsif ($in =~ m/^\@F /) { $in =~ s/^\@F //; my ($sofar, $remains) = split(/ /, $in); $self->{sofar} = sprintf("%d:%02d", int($sofar / 60), $sofar % 60); $self->{remains} = sprintf("%d:%02d", int($remains / 60), $remains % 60); } } sub play { my $self = shift; my $song = shift; print { $self->{write} } "load $song\n"; } sub state { my $self = shift; return $self->{state}; } sub toggle { my $self = shift; print { $self->{write} } "pause\n"; } sub pause { my $self = shift; print { $self->{write} } "pause\n" if $self->state() == 2; } sub resume { my $self = shift; print { $self->{write} } "pause\n" if $self->state() == 1; } sub seek { my $self = shift; my $position = shift; $position *= 39; print { $self->{write} } "jump $position\n"; } sub stop { my $self = shift; print { $self->{write} } "quit\n"; } 1; __END__ #### #!/usr/bin/perl $| = 1; use Audio::Play::MPG321; $player = new Audio::Play::MPG321; $SIG{CHLD} = 'IGNORE'; $SIG{INT} = sub { $player->stop(); exit 1; }; do { while (1) { $player->poll(); select(undef, undef, undef, 0.5); } } unless fork(); while (1) { print "\n> "; chomp(my $in = ); my ($method, @args) = split(/\s+/, $in); $player->$method(@args); print $player->state(), "\n"; }