The tkmpg123 program is an MPG player based on Apple's itunes. The explanation and demonstration can be found in Chapter 15, "Anatomy of the MainLoop".
#!/usr/local/bin/perl -w
#
# tkmpg123 - keep mpg123 and Tk happily eventing w/o blocking.
#
# Stephen.O.Lidie@Lehigh.EDU, 2001/04/17.
use Audio::Play::MPG123;
use Tk;
use Tk::PNG;
use subs qw/build_player start_play edit_menuitems file_menuitems
help_menuitems init play/;
our ($c, , @info, $infov, $mw, $paus, $phand, $play, $player, $timev, $v);
use strict;
$v = '-0.97';
$player = Audio::Play::MPG123->new;
$phand = $player->IN;
$mw = MainWindow->new;
$mw->configure(-menu => my $menubar = $mw->Menu);
map {$menubar->cascade( -label => '~' . $_->[0], -menuitems => $_->[1] )}
['File', file_menuitems],
['Edit', edit_menuitems],
['Help', help_menuitems];
build_player;
MainLoop;
sub build_player {
$c = $mw->Canvas(
-width => 1,
-height => 1,
-background => 'dark slate gray',
)->pack;
my $itunes = $c->Photo(-file => 'images/itunes.gif');
$c->createImage(0, 0,
-image => $itunes,
-tag => 'itunes',
-anchor => 'nw',
);
$c->configure(-width => $itunes->width, -height => $itunes->height);
$paus = $c->Photo(-file => 'images/paus.gif');
$play = $c->Photo(-file => 'images/play.gif');
$c->createImage(80, 40, -image => $play, -tag => 'play-image');
$c->bind('play-image', '<1>' => \&pause);
my $green = '#d5dac1';
my $font = 'courier 12';
my $f = $c->Frame(
-width => 250,
-height => 50,
-background => $green,
-relief => 'sunken',
-borderwidth => 3,
);
$f->packPropagate(0);
$c->createWindow(170, 20, -anchor => 'nw', -window => $f);
$infov = '';
my $info = $f->Label(
-textvariable => \$infov,
-font => $font,
-background => $green,
);
$info->pack(-side => 'top');
$timev = 'Elapsed Time: 0:00';
my $time = $f->Label(
-textvariable => \$timev,
-font => $font,
-background => $green,
);
$time->pack(-side => 'top');
my $f2 = $c->Frame(
-width => 570,
-height => 280,
-background => $green,
-relief => 'sunken',
-borderwidth => 3,
);
$f2->packPropagate(0);
$c->createWindow(15, 85, -anchor => 'nw', -window => $f2);
my $mpgs = $f2->Scrolled('Listbox')->pack(-fill => 'y', -expand => 1);
foreach my $mpg (<*.mpg>, <*.mp3>) {
$mpgs->insert('end', $mpg);
}
$mpgs->bind('<1>' => sub {play $mpgs->get( $mpgs->nearest($Tk::event->y) )});
} # end build_player
sub pause {
$player->pause;
$c->itemconfigure('play-image',
-image => ($player->state == 1) ? $paus : $play
);
}
sub edit_menuitems {
[
['command', 'Preferences ...', -command => sub {$mw->bell}],
];
}
sub file_menuitems {
[
[
qw/cascade ~Play -menuitems/ =>
[
[qw/command ~File... -command/ => \&play_file],
[qw/command ~URL... -command/ => \&play_url],
],
],
[qw/command ~Quit -command/ => \&exit],
];
}
sub help_menuitems {
[
['command', 'Version', -command => sub {print "Version $v\n"}],
'',
['command', 'About', -command => sub {print "Playing songs\n"}],
];
}
sub play_file {
play $mw->getOpenFile(-title => 'Pick A Song');
}
sub play_url { # for now
my $song = 'http://www.lehigh.edu/sol0/beat.mpg';;
play $song;
}
sub play {
my $song = shift;
print "song=$song!\n";
if (defined $song) {
$player->load($song);
@info = map {$player->$_} qw/title artist album/;
start_play;
}
}
sub ctm {
my $s = shift;
my $m = int($s / 60);
sprintf("%02d:%02d", $m, $s - $m * 60);
}
sub start_play {
my $info_tid = $mw->repeat(5000 => sub {
$infov = $info[0];
unshift @info, pop @info;
});
my $time_tid = $mw->repeat(1000 => sub {
my(@toks) = split ' ', $player->stat;
$timev = sprintf( "Elapsed Time: %s of %s\n",
&ctm($toks[3]), &ctm($toks[3] + $toks[4]) );
});
my $in_hand = sub {
$player->poll(0);
$mw->update;
if ($player->state == 0) {
$player->stop;
$mw->fileevent(\$phand, 'readable' => '');
$mw->afterCancel($info_tid);
$mw->afterCancel($time_tid);
}
};
$mw->fileevent(\$phand, 'readable' => $in_hand);
}
Copyright © 2002 O'Reilly & Associates. All rights reserved.