#!/usr/X386/bin/wishx -f
#
#	 #########	   #	   # ######### #
#		#	    #	  #  #	       #
#	      ##   #	 #   #	 #   #	       #
#	     #	   #	 #    ###    #######   #
#	   ##	   #	 #   #	 #   #	       #
#	  #	   #	 #  #	  #  #	       #
#	 #########  ###### #	   # ######### #########
#			 #
#			 #
#		    #####
#
#
#	A Tcl/Tk interface to the ZyXEL control program written by 
#	Rob Janssen, PE1CHL
#
#	This wish script is nothing more than a graphical interface
#	to replace the cumbersome zvbm script. 
#
#	It also talks to the ZyXEL programm through the fifo
#	(usaully /usr/ZyXEL/fifo.ttyS<x>). 
#	Replies are read through another fifo.
#
#	Features:
#	- playback recorded messages
#	- archive messages
#	- listen to or record a phone call
#	- modem status information
#	- fax viewing through external convertor + viewer
#
#
#
#	Copyright 1994 by Harm Arts (harm@es.ele.tue.nl)
#
#	Permission is hereby granted to copy, reproduce, redistribute,
#	or otherwise use this software as long as: there is no monetary
#	profit gained specifically from the use or reproduction or this
#	software, it is not sold, rented, traded or otherwise marketed,
#	and this copyright notice is included prominently in any copy
#	made.
#
#	The author make no claims as to the fitness or correctness of
#	this software for any use whatsoever, and it is provided as is.
#	Any use of this software is at the user's own risk.
#
#
#
#	$Id: voice,v 2.4 1994/10/22 14:59:21 root Exp $

#############################################################################
# configure as you like
#############################################################################

# debuging info on stdout [0|1]
set debug	0

# how to search for the fifo to talk to ZyXEL ($fdir.<tty>)
set fdir	/usr/ZyXEL/fifo

# fifo to read what ZyXEL program answers
set infile	/tmp/ZyXEL.fifo

# directories in which you store your play files and how to name them
set playdirs  { "/usr/ZyXEL/play	Play"
		"/usr/ZyXEL/archive	Archive"
		"/usr/ZyXEL/record	Recorded"
		"/usr/ZyXEL/fax		Fax" }

# index in playdirs to start up with
set defaultdir	2

# list of indices in playdirs which may be archived
set toarchive { 2 }

# index in playdirs to use as archive
set archivedir	1

# index in playdirs where the ZyXEL programm puts recordings in
set recdir	2

# default for speaker: internal or line
set speaker	internal

# default volume for speaker [0-7]
set defvol	6

# how to convert a CLASS 2 fax file into a visible file
set fax2vis	"/home/harm/linux/apps/netpbm/pbm/g3topbm -rev -stretch"

# what extensio does the visible file have
set visext	pbm

# how to view a visible fax file
set visview	"xv -maxpect -geometry +0+0"

#############################################################################
# procs
#############################################################################

foreach i [winfo child .] {
    catch {destroy $i}
}

proc tkerror err {
    global errorInfo
    puts stderr "$errorInfo"
}

proc Puts {s} {
    global debug
    if {$debug} { puts stdout $s }
}

proc mkDialog {w msgArgs args} {
    catch {destroy $w}
    toplevel $w -class Dialog
    set oldFocus [focus]
    
    frame $w.top -relief raised -border 1
    frame $w.bot -relief raised -border 1
    pack $w.top $w.bot -side top -fill both -expand yes
    
    eval message $w.top.msg -justify center \
	    -font -bitstream-*-medium-*-*-*-*-150-*-*-m-*-*-* $msgArgs
    pack $w.top.msg -side top -expand yes -padx 2 -pady 2
    
    if {[llength $args] > 0} {
	set arg [lindex $args 0]
	frame $w.bot.0 -relief sunken -border 1
	pack $w.bot.0 -side left -expand yes -padx 10 -pady 10
	button $w.bot.0.button -text [lindex $arg 0] \
		-command "[lindex $arg 1]; destroy $w; focus $oldFocus"
	pack $w.bot.0.button -expand yes -padx 6 -pady 6
	bind $w <1> "$w.bot.0.button config -relief sunken"
	bind $w <ButtonRelease-1> \
		"[lindex $arg 1]; $w.bot.0.button deactivate; destroy $w; focus $oldFocus"
	bind $w <Return> "[lindex $arg 1]; destroy $w; focus $oldFocus"
	focus $w
	
	set i 1
	foreach arg [lrange $args 1 end] {
	    button $w.bot.$i -text [lindex $arg 0] \
		    -command "[lindex $arg 1]; focus $oldFocus"
	    pack $w.bot.$i -side left -expand yes -padx 10
	    set i [expr $i+1]
	}
    }
    wm geometry $w +300+150
}

proc MkList {dir} {
    global visext
    while {[.sb.list size] > 0} {
	.sb.list delete 0
    }
    foreach sdir $dir {
	foreach i [exec ls $sdir] {
	    # hide intermediate files
	    if { [string last .$visext $i] == -1 } {
		.sb.list insert end $i 
	    }
	}
    }
}

proc Pout {string} {
    global pout
    Puts "pout : $string"
    puts $pout $string;	flush $pout
}

proc MkBusy {val} {
    global busy
    set busy $val
    if {$busy >  0} {set state normal} else {set state disabled}
    .buttons.stop		config -state $state
    if {$busy == 0} {set state normal} else {set state disabled}
    .buttons.play		config -state $state
    .buttons.record		config -state $state
    .buttons.listen		config -state $state
    .buttons.status		config -state $state
    .speaker.vol.sc		config -state $state
    .speaker.out.internal	config -state $state
    .speaker.out.line		config -state $state
}

proc CheckOk {} {
    global busy
    global Zpid
    .buttons.stop	config -command {
	.buttons.stop	config -state disabled
	set pslist	[exec ps a]
	Puts "exe: kill -2 $Zpid"
	exec kill -2 $Zpid 
    }
    MkBusy [expr $busy+1]
    signal trap SIGALRM {
	global pin
	set flist [select $pin {} {} 0]
	if {[lindex $flist 0] == $pin} {
	    gets $pin answer
	    if {$answer != "" && $answer != "\r"} {		
		Puts "tim  : $answer" 
	    }
	    if {[string first OK    $answer] == 0 ||
	    [string first ERROR $answer] == 0 } {
		MkBusy [expr $busy-1] 
	    }
	}
	if {$busy >  0} { alarm 0.1 } 
    }
    alarm 0.1
}

proc Play {file} {
    set ext_index [string last . $file]
    set ext [string range $file [expr $ext_index + 1] end]
    if {"$ext" == "fax"} {
	global visext
	global visview
	set base [string range $file 0 $ext_index]
	if {![file exists $base$visext] } {
	    mkDialog .wait "-text {Converting fax to $visext.
	    This might take a while ...} \
		    -justify left"
	    update
	    global fax2vis
	    eval [concat exec \
		    $fax2vis $file > $base$visext 2>@ stderr]
	    destroy .wait
	}
	Puts "starting $visview $base$visext"
	eval [concat exec $visview $base$visext &]
    } else {
	CheckOk
	Pout "P $file"
    }
}

proc WaitOk {string} {
    global pin
    set answer ""
    while {[string first $string $answer] != 0 &&
    [string first ERROR   $answer] != 0} {
	gets $pin answer
	if {$answer != "" && $answer != "\r"} {		
	    Puts "pin  : $answer" 
	} 
    }
}	

proc Volume {l} { Pout ATL$l ; WaitOk OK }

#############################################################################
# start packing
#############################################################################

set id	{$Id: voice,v 2.4 1994/10/22 14:59:21 root Exp $}
set version [lindex $id 2]
label .label -text "ZyXEL user interface, Version $version. (C) Harm Arts" \
	-relief raised -borderwidth 2
pack  .label -side top -fill both

frame .speaker -relief raised -borderwidth 2
frame .speaker.out
frame .speaker.vol

label		.speaker.out.label \
	-text "Speaker output:"
radiobutton 	.speaker.out.internal \
	-text "Internal" -relief flat \
	-value "internal" -variable speaker \
	-activebackground Bisque1 \
	-command { Pout "S"; WaitOk SPEAKER}
radiobutton	.speaker.out.line \
	-text "Line" -relief flat \
	-value "line" -variable speaker \
	-activebackground Bisque1 \
	-command { Pout "L"; WaitOk LINE}
scale		.speaker.vol.sc \
	-orient horizontal -length 10 -from 0 -to 7 \
	-showvalue no  -tickinterval 1 -bg Bisque1 \
	-command { Volume } -length 100 -sliderlength 10
label 		.speaker.vol.label \
	-text "Speaker volume:"

pack .speaker.out.label .speaker.out.internal .speaker.out.line \
	-side left -pady 2
pack .speaker.vol.label .speaker.vol.sc -side left -fill both -padx 5
place .speaker.vol.label -x 0
pack .speaker.out .speaker.vol -side top
pack .speaker -fill x

.speaker.vol.sc		set $defvol
.speaker.out.internal	[expr "{$speaker}=={internal} ? {select} : {deselect}"]
.speaker.out.line	[expr "{$speaker}!={internal} ? {select} : {deselect}"]


frame .sb -relief raised -borderwidth 2
frame .sb.rb

set i 1
foreach arg $playdirs {
    radiobutton .sb.rb.$i \
	    -variable dir -text "[lindex $arg 1]" -relief flat \
	    -value [lindex $arg 0] -activebackground Bisque1 \
	    -command { MkList $dir }
    pack .sb.rb.$i -side left
    set i [expr $i+1]
}

scrollbar   .sb.scroll \
	-command ".sb.list yview"

# pack .sb.rb.play .sb.rb.arc .sb.rb.rec -side left -anchor w
pack .sb.rb -side top -anchor w
pack .sb.scroll -side left -fill y
listbox .sb.list -yscroll ".sb.scroll set" -geometry 20x20 \
	-setgrid yes
pack .sb.list -side right -fill both -expand yes

bind .sb.list <Double-Button-1> {
    .buttons.play invoke
}

frame .buttons -relief raised -border 1
pack .sb .buttons -side left -fill both -expand yes

button .buttons.stop    -text "Stop" 
button .buttons.play    -text "Play" 
button .buttons.arch    -text "Archive" 
button .buttons.listen	-text "Listen"
button .buttons.record	-text "Record"
button .buttons.status  -text "Status"
button .buttons.delete  -text "Delete" 
button .buttons.exit    -text "Exit"

pack	.buttons.stop   .buttons.play   .buttons.arch   .buttons.listen \
	.buttons.record .buttons.status .buttons.delete .buttons.exit   \
	-side top -fill both

.buttons.stop	config -state disabled
.buttons.play	config -command {
    if {[selection own] != ""} {
	foreach i [selection get] { 
	    Play $dir/$i
	}
    }
}
.buttons.arch	config -command {
    if { [selection own] != "" &&
    [lsearch $toarchive [lsearch -glob $playdirs $dir*]] != -1 } {
	while { [llength [.sb.list curselection]] > 0 } {
	    set index [lindex [.sb.list curselection] 0]
	    exec mv $dir/[.sb.list get $index] $archive
	    .sb.list delete $index
	}
    }
}
.buttons.listen	config -command {
    Pout "ATM2H1"
    WaitOk OK
    .buttons.stop	config -command {
	MkBusy 0; Pout "ATH0"; WaitOk OK
    }
    MkBusy 1
}
.buttons.record	config -command {
    set dir [lindex [lindex $playdirs $recdir] 0]
    Pout "R2"
    CheckOk
    MkList $dir
}
.buttons.status config -command {
    Pout "ATI2"; global pin; set answer ""; set text ""
    while { [string first OK    $answer] != 0 &&
    [string first ERROR $answer] != 0} {
	if {$answer != ""} {
	    set text $text\n[string trim $answer " \r"]
	}
	gets $pin answer
    }
    mkDialog .status "-text {$text} -justify left" "OK {}"
}
.buttons.delete config -command {
    if {[selection own] != ""} {
	while { [llength [.sb.list curselection]] > 0 } {
	    set index [lindex [.sb.list curselection] 0]
	    set file  [.sb.list get $index]
	    set ext   [string last .fax $file]
	    exec rm -f $dir/$file
	    if { $ext > -1 } {
		set base [string range $file 0 $ext]
		Puts "also removing $dir/$base$visext"
		exec rm -f $dir/$base$visext
	    }
	    .sb.list delete $index
	}
    }
}
.buttons.exit	config -command {
    destroy .
}

#############################################################################
# initialize
#############################################################################

wm geometry . 30x9+50+100

set busy	0

set dir		[lindex [lindex $playdirs $defaultdir] 0]
set archive	[lindex [lindex $playdirs $archivedir] 0]

MkList $dir

switch $argc {
    0 { set fifo [exec sh -c "ls $fdir.*" | head -1] }
    1 { set fifo $fdir.$argv }
    default { puts stdout "Usage: $argv0 [ttySx]"; exit } 
}

if {[file exists $infile]} {
    if {[file type $infile] != "fifo"} {
	puts stdout "Error: $infile allready exists and is not a fifo"
    }
} else {
    exec mkfifo $infile
}

set pout [open $fifo w]
Puts "pout $fifo open"
Pout "> $infile"
set pin  [open $infile]
Puts "pin  open"
Pout "#"
WaitOk ZyXEL
Pout "!"
gets $pin Zpid
Puts "Zpid = $Zpid"

#############################################################################
# now push and see what all buttons do
#############################################################################

