#!/usr/local/bin/perl -w

#
# vtwiz, (c) 1999, j. borgert, borgert@theo-physik.uni-kiel.de
#
# purpose: ------------------------------------------
#
#   GUI for alevt by E. Toernig
#
#   alevt itself is not capable of switching stations
#   so I wrote this script that greps ~./xawtv for 
#   valid station names, uses set-tv to set one 
#   selected via a listbox and fires up aletv with it.
#
#   with aletv running, selecting another (different)
#   station leads to an explicit kill (ouch...) and 
#   restart of alevt with the new one... so inventing
#   channel switching to alevt...
#
#   you could also put in a page number by an entry
#   which is selected at startup...
#
#   alevt is handled its own methods once it runs.
#   see alevt's documentation (page 900 or 'h' key)
#   for usage.
#  
#
# what you need: ------------------------------------
# - alevt        (used for coding: 1.4.9)
# - Tk           (used for coding: 800.014, 
#                    but 400something should also work...)
# - Proc::Simple (used for coding: 1.12)
#                (try CPAN www.cpan.org for the former two.)
# - xawtv/set-tv (used for coding: 2.35)
# - have xawtv up running and performed station scan
#                ( ~./xawtv has to exists)
# - have set-tv working 
#                (should if xawtv works)
# - an by the way: have perl running (who has not?)
#                (used for coding: 5.005_03) 
#
#
# to do:
# - add xawtv start up method
# - prevent alevt from running when any other v4l app is running
# - add options (default pages, mark stations that do have no VT)
# - add capture like access to pages (by alevt-cap)
# - ...
# - suggestions? c above for e-mail
#
# ---------------------------------------------------
#
# have fun...
#

#------------- packages -----------------------------------------------

use Tk;
use Proc::Simple;

#------------- inits ---------------------------------------------------

my $page = 100;
my $alevt_commandline = "alevt";
my $alevt = Proc::Simple->new( );

#-------------- read'in stations ---------------------------------------

#
# get users homedir from environment
#
$homedir = $ENV{HOME};
open( XAWFILE, "$homedir/.xawtv" ) or die "Cannot open ~/.xawtv\n";

my @stations;
LINE:
while( <XAWFILE> ) {
    next LINE unless /\[(.+)\]/; # only take station names 
                                 # (in square brakets brakes)
    push @stations, $1;
}

close XAWFILE;

#----------------------------------- the GUI ----------------------------

my $top = MainWindow->new( -title => 'vtwiz' );

#
# listbox to hold the stations
#
my $listbox = $top->ScrlListbox( -label => 'vtwiz, (c) 1999, j. borgert',
				   -selectmode => 'single',
				   -exportselection => 0 );
$listbox->pack( -side => 'top', -expand => 'yes', -fill => 'both' );

#
# put station names into the listbox
#
for (@stations) {
  $listbox->insert( 'end', $_ );
}

#
# select the first entry (0) as default...
#
$listbox->selectionSet( 0 );

#
# buttons ('fire up' and 'quit')
#
my $buttonframe = $top->Frame( );
my $firebutton = $buttonframe->Button( -text => 'Start alevt',
				       -command => \&fire,
				       -relief => 'groove' );
$firebutton->pack( -side => 'left' );
my $quitbutton = $buttonframe->Button( -text => 'Quit',
				       -command => \&godown,
				       -relief => 'groove' );
$quitbutton->pack( -side => 'right' );
$buttonframe->pack( -side => 'bottom', 
		    -expand => 'yes', -fill => 'x',
		    -padx => 5, -pady => 5 );

#
# page number entry.
# change default page number at the top in
# the 'inits' section.
#
my $pageframe = $top->Frame( );
my $pagelabel = $pageframe->Label( -text => 'page to start up with:',
				   -justify => 'right' );
my $pageentry = $pageframe->Entry( -textvariable => \$page,
				   -width => 3 ); 
$pagelabel->pack( -side => 'left', 
		  -expand => 'yes', -fill => 'x' );
$pageentry->pack( -side => 'left', 
		  -expand => 'no' );
$pageframe->pack( -side => 'bottom', 
		  -expand => 'yes', -fill => 'x',
		  -padx => 5, -pady => 5 );

#
# look after alevt and change button text if not running
#
$top->repeat( 1000, \&look_after_alevt );

#
# what do u think?
#
MainLoop;

#---------------------- subs ------------------------------------


#
# sub to manage set-tv and alevt execution
#
sub fire {

  #
  # check for legal page numbers 
  # which is defined bu the grace of the 
  # script to be a three digit number
  #
  if( $page !~ /\d\d\d/ ) {
    mmsg( "illegal page number\n" );
    return 0;
  }

  #
  # get the station...
  #
  my $station = $listbox->Getselected( );
  mmsg( "no station selected yet" ) unless defined $station;

  if( defined $station ) {

    #
    # kill alevt if alredy running -> 'Change station'
    #
    if( $alevt->poll( ) ) {
      $alevt->kill( ) or die "Not been able to kill (bummer...)\n";
    }

    # 
    # perform set-tv action...
    # (not using Proc::Simple here to prevent 
    # the set-tv messages from showing in the shell
    # or elsewhere... works well for just a little
    # v4l debug info still displayed... 
    #      heck, make an icon to fire vtwiz up
    #      and u will not see it.)
    #
    my $commandline = "set-tv '$station' |";
    my $output;
    open( SETTV, $commandline ) or die "Cannot run programm: $!";
    while( <SETTV> ) {
      $output .= $_;
    }
    close( SETTV );
    # output of set-tv is now in $output...
    # might be used for future status line or such thingys
    
    #
    # start up aletv by Proc::Simple (fork...)
    #
    $commandline = "$alevt_commandline $page";
    unless( $alevt->poll( ) ) {
      $alevt->start( $commandline ) or die "Cannot start alevt\n";
      $firebutton->configure( -text => 'Change station' );
    } else {
      # should not happen... killed above... 
      # but aren't we all a bit paranoid 
      mmsg( "alevt is already running, nerd!" );
    }
  }

  #
  # if anything went wrong turn the button to 'up'
  #
  unless( $alevt->poll( ) ) {
    $firebutton->configure( -text => 'Start alevt' );
  }

  return 1;
}

#
# kill alevt when I am killed...
# (would live on otherwise... cause it has been
# forked...)
#
sub godown {
  if( $alevt->poll( ) ) {
    $alevt->kill( ) or die "Not been able to kill (bummer...)\n";
  }
  exit 0;
}


#
# mmsg( message[, title] );
# creates new toplevel with title 
# for display of message 
#
sub mmsg {
  my $msg = shift;
  my $tit = shift;

  $tit = 'error' unless defined $tit;
  
  my $toplevel = $top->Toplevel( -title => "$tit" );
  $toplevel->Message( -text => "$msg", -width => '10c' )->pack( );
  $toplevel->Button( -text => 'Ok', 
		     -command => sub {
		       $toplevel->destroy( )
		     } )->pack( );
  return 1;
}
  

#
# called by repeat every 1000ms.
# looks if alevt is still up (polling...)
# if not turn button to 'up' again.
#
sub look_after_alevt {
  unless( $alevt->poll( ) ) {
    $firebutton->configure( -text => 'Start alevt' );
  }
  return 1;
}
