IO::Select so cool

ethan on 2002-11-16T17:04:28

I am using a hand-rolled MP3 player for the console to circumvent the limitations that mpg123 has. It's using the brilliant MPEG::MP3Play as backend which even has such goodies as a nice equalizer etc. With the help of Term::ReadKey my players response to single key-strokes: 'e' for editing the tag, '>' for next song, '<' for previous song, '+' turning volume up and so on.

My playlist however has too many songs I prefer to skip. Since I always have my player on a virtual console I have to switch to it when skipping a song and being under X. I am a little concerned with the lifetime of my monitor if I do that a few hundred times a day (you probably know this 'click' of the relais inside a monitor).

So I thought it'd be cool if I had a sort of remote control that I could associate with a WindowMaker application icon: one click and the song is skipped or so. I thought: Hey, that's easy, I just need to integrate a socket server into my player so I went for IO::Socket::INET and IO::Select.

The event loop of the player is actually simple: two nested while loops:



while () {

my $k; while (not defined ($k = ReadKey(-1))) { # process the updating of the display with MPEG::MP3Play # methods: yes, my player even has a counter for the playing time ... } # process key-strokes here

}


Making my player networkish just required a few lines of code and no change of the overal control-flow. The above now looks as follows:

while () {

my $k; while (not defined $k and not defined ($k = ReadKey(-1))) { my @s = $select->can_read(0.1/10); for my $fh (@s) { if ($fh == $socket) { $select->add($socket->accept); } else { $fh->sysread($k, 1); } } # display update } # key-stroke processing }


Along with two lines for the creation of the IO::Socket::INET and IO::Select object this is a total addition of just 10 lines of code!

A simple text mode client adds another couple of key-strokes. Same pattern really:

while () { my $key; while (not defined ($key = ReadKey(-1))) { } exit if $key eq '#'; syswrite $sock, $key, 1; if ($key eq 'q') { $sock->close; exit; } }

I am pretty pleased!