in reply to Dynamically altering Tk buttons

...here is an example for you to check out

... the problem is how do you detect the end of playback... is some signal emitted?

.... i leave the state logic broken, for you to figure out :-)

#!/usr/bin/perl use strict; use warnings; use Tk; my $mw = Tk::MainWindow->new; my $button = $mw->Button->pack(-side =>'left'); my $button1 = $mw->Button(-text => 'Go ', -state => 'normal')->pack( -side =>'left'); my $x = $mw->Pixmap( -data => qq(/* XPM */ static char * x_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " ... ... ", " .. .. ", " ... .. ", " .. ... ", " .... ", " ... ", " ... ", " .... ", " .. .. ", " ... .. ", " .. ... ", " .. .. ", " ... ... ", " ", " ", " ", " ", " "}; )); my $o = $mw->Pixmap( -data => qq(/* XPM */ static char * o_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " ...... ", " ........ ", " ... ... ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " ... ... ", " ........ ", " ...... ", " ", " ", " ", " ", " "}; )); my @toggle = ($x, $o); my @toggle1 = ('Go ','Whoa'); $button->configure( -image => $x, -command => sub { @toggle = @toggle[1, 0]; @toggle1 = @toggle1[1, 0]; $button->configure(-image => $toggle[0]); if ( $toggle1[0] eq 'Go '){ $button1->configure( -text => $toggle1[0], -state => 'normal', ); }else{ $button1->configure( -text => $toggle1[1], -state => 'disabled', ); } } ); Tk->MainLoop;

I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku

Replies are listed 'Best First'.
Re^2: Dynamically altering Tk buttons
by Llew_Llaw_Gyffes (Scribe) on Jan 04, 2010 at 16:31 UTC

    Yup, I found that method myself, after some digging.

    How I'm detecting the end of playback is a little sneaky.  I'm spawning the CLI MP3 player application like this:

    $cmd = sprintf($opts{playercmd}, ($listbox->getRow($i))[0]); $player_pid = open($PLAYER, "|$cmd");

    This gets me a blocking open on the player, so that I don't ever get two tracks playing at once, and a child PID back.  But, the child player doesn't terminate on exit.  So then I poll /proc/pid/status every 50ms in my non-Tk event loop, and wait for the status to change to 'zombie', at which point I know playback has finished.  Then I can close the player handle, do any necessary processing, and advance to the next track.  The 50ms response time is too short for the listener to notice, but slow enough in system terms that the task load from the polling is down in the noise.

      and wait for the status to change to 'zombie'

      ha ha ha.... that has got to be the funkiest hack i've ever seen....... didn't they teach you at wizard school to never, NEVER allow zombies even into existence?.... still laughing

      To give you a clue: once you have the filehandle to the process, you can watch for the filehandle( or its filenum' ) to be closed , and then do a kill -9 on the $parent_pid ..... see Perl/Tk front-end to mplayer for other ideas


      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku

        Yes, looking for the filehandle to close is what I tried first, but it appeared it wasn't ever closing unless I closed it myself.  SO I needed a way to determine when I could safely close it, and this is what I came up with.  I'm sure there must be better ways; I just haven't come up with one that works yet and still allows me to periodically poll it, rather than just waiting on it and blocking until it terminates.  I need to balance "only one player child is allowed to run at a time" vs. "the rest of the app must not block while waiting for the player to exit".