diff intercom/intercom.tcl @ 2:13be24d74cd2

import intercom-0.4.1
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 09:57:52 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/intercom/intercom.tcl	Fri Jun 25 09:57:52 2010 +0200
@@ -0,0 +1,513 @@
+#!/usr/bin/wish
+
+# intercom.tcl
+#
+# Copyright (C) DFS Deutsche Flugsicherung (2004, 2005). 
+# All Rights Reserved.
+# Author: Andre Adrian
+#
+# Voice-over-IP Intercom Graphical User Interface
+#
+# Version 0.3.7
+# open all UDP sockets before use to fix problem with slow CPUs
+
+
+# UDP "connection" extension for Tcl/Tk
+load /usr/local/lib/libudp1.0.6.so
+
+# ##############################################################
+# Begin Belegt [IS_30] und Umleitung [IS_41] Remote Signallisierung
+
+# intercom.tcl to other intercom.tcl Signalling Receive init
+proc rsig_recv_init {port} {
+  set srv [udp_open $port]
+  fconfigure $srv -buffering none -translation binary
+  fileevent $srv readable [list ::rsig_recv $srv]
+  # puts "Listening on udp port: [fconfigure $srv -myport]"
+  return $srv
+}
+
+# intercom.tcl to other intercom.tcl Signalling Send init
+proc rsig_send_init {host} {
+  global rsig_send_sock
+  
+  set s [udp_open]
+  fconfigure $s -remote [list $host 55004]
+  set rsig_send_sock($host) $s
+}
+
+# intercom.tcl to other intercom.tcl Signalling Send
+proc rsig_puts {host str} {
+  global rsig_send_sock
+  
+  puts $rsig_send_sock($host) $str
+  flush $rsig_send_sock($host)
+}
+
+# intercom.tcl from other intercom.tcl Signalling Receive
+proc rsig_recv {sock} {
+  global ip2tmap tping
+  global t_updown umltgmap myipaddr
+
+  set msg_body [read $sock]
+  set msg_header [fconfigure $sock -peer]
+  # puts "udp_server: $msg_header: [string length $msg_body] {$msg_body}"
+  
+  # to partner is first argument in msg_body
+  set argv [split $msg_body]
+  set ip_to [lindex $argv 1]
+  set t_to $ip2tmap($ip_to)
+  
+  # from partner is taken from msg_header
+  set conn [lindex $msg_header 0]
+  set ip_from [lindex $conn 0]
+  set t_from $ip2tmap($ip_from)
+  
+  switch [lindex $argv 0] {
+    p {rsig_puts $ip_from "q $ip_to"   ;# got application ping
+    }
+    q {set tping ""   ;# got application ping response (pong)
+    }
+    c {.$t_from configure -highlightbackground cyan   ;# got call setup
+       incr t_updown($t_from)
+       .$t_to configure -highlightbackground cyan
+       incr t_updown($t_to)
+    }
+    h {incr t_updown($t_from) -1    ;# got hangup
+      if {$t_updown($t_from) <= 0} {
+        set t_updown($t_from) 0
+        .$t_from configure -highlightbackground "#d9d9d9"
+      }
+      incr t_updown($t_to) -1
+      if {$t_updown($t_to) <= 0} {
+        set t_updown($t_to) 0
+        .$t_to configure -highlightbackground "#d9d9d9"
+      }
+    }
+    d { # puts "rsig_recv ip_from=$ip_from ip_to=$ip_to"
+      set umltgmap($ip_from) $ip_to   ;# got diversion
+      # foreach i {1 2 3 4 5 6 7 8} {
+      #   puts "umltgmap(10.232.35.$i) = $umltgmap(10.232.35.$i)"
+      # }
+    }
+    default {puts "rsig_recv unknown msg=$msg_body"}
+  }
+  return
+}
+
+# End Belegt [IS_30] und Umleitung [IS_41] Remote Signallisierung
+
+# ##############################################################
+# Begin Stoerung Signalisierung [IS_31]
+
+proc checkping {} {
+  global tping
+  
+  #puts "checkping $tping"
+  if {$tping != ""} {
+    .$tping configure -background red
+    .$tping configure -activebackground red
+    .$tping configure -highlightbackground red
+  }
+}
+# End Stoerung Signalisierung [IS_31]
+
+# ##############################################################
+# Direct Access Button
+
+# View relevant function Arbeiter
+proc da_update {t state} {
+  switch $state {
+  0 { .$t configure -foreground black         ;# nothing
+      .$t configure -activeforeground black
+      .$t configure -background "#d9d9d9"     ;# button is grey
+      .$t configure -activebackground "#d9d9d9"}
+  1 { .$t configure -foreground black         ;# transmit
+      .$t configure -activeforeground black
+      .$t configure -background yellow     
+      .$t configure -activebackground yellow}
+  2 { .$t configure -foreground black         ;# receive
+      .$t configure -activeforeground black
+      .$t configure -background magenta      
+      .$t configure -activebackground magenta}
+  3 { .$t configure -foreground black         ;# full duplex
+      .$t configure -activeforeground black
+      .$t configure -background green
+      .$t configure -activebackground green}
+  }
+}
+
+# View relevant function Vorarbeiter
+proc da_ca_update {t state} {
+  global ta_ip ip2tmap
+  
+  # update DA button
+  da_update $t $state
+  
+  if {[info exists ip2tmap($ta_ip)]} {
+    set t_alias $ip2tmap($ta_ip)
+  } else {
+    set t_alias ""
+  }
+  
+  # Update Common Answer Button
+  if { $t_alias == $t } {
+    da_update ta $state
+  }
+}
+
+# DA/CA button press callback
+proc da_keyPress {t} {
+  global t2ipmap state lsig_sock longKey tping umltgmap ip2tmap
+  
+  set longKey($t) 0   ;# 1 wenn Taste lange gedrückt, sonst 0  
+  set ip $t2ipmap($t) ;# ip des remote intercom.tcl 
+  set uip $umltgmap($ip) ;# Umleitung auf gleiche IP oder andere IP
+
+  # avoid two connections to one partner in case of diversion
+  if {$ip != $uip} {
+    if {$state($t) == 0 || $state($t) == 2} {
+      set tumltg $ip2tmap($uip)
+      if {$state($tumltg) == 1 || $state($tumltg) == 3} {
+        puts "da_keyPress: error: already connection to this partner"
+        return
+      }
+    }
+  }
+
+  # remote signalling
+  switch $state($t) {
+  0 {set cmd c
+    after 300 [list set longKey($t) 1]
+    rsig_puts $uip "p $uip"  ;# send application ping
+    set tping $t
+    after 200 [list checkping]}
+  1 {set cmd h}
+  2 {set cmd c
+    after 300 [list set longKey($t) 1]
+    rsig_puts $uip "p $uip"  ;# send application ping
+    set tping $t
+    after 200 [list checkping]}
+  3 {set cmd h}
+  }
+
+  # local signalling to intercomd - maybe with diversion
+  puts $lsig_sock "$cmd $uip"
+  flush $lsig_sock
+  
+  # local signalling intercom.tcl - with no diversion
+  switch $cmd {
+  c {tx_begin $ip}
+  r {rx_begin $ip}
+  h {tx_end $ip}
+  d {rx_end $ip}
+  }
+  
+# Begin Belegt Signalisierung [IS_30]
+  foreach i {t1 t2 t3 t4 t5 t6 t7 t8} {
+    set da_ip $t2ipmap($i)
+    rsig_puts $da_ip "$cmd $uip"
+  }
+# End Belegt Signalisierung [IS_30]
+}
+
+# DA/CA button release callback
+proc da_keyRelease {t} {
+  global longKey
+  
+  if {$longKey($t)} {
+    keyPress $t
+  }
+}
+
+# ##############################################################
+# Common Answer Button Req IS_14
+
+proc ca_update {} {
+  global ta_ip textmap
+  
+  # puts "ca_update $ta_ip"
+
+  if {[info exists textmap($ta_ip)]} {
+    set ta_text $textmap($ta_ip)
+  } else {
+    set ta_text $ta_ip
+  }
+  .ta configure -text $ta_text 
+}
+  
+# ##############################################################
+# Diversion (Umleitung) Req. IS_41
+
+# Update Umleitungstaste Req. IS_41
+proc umltg_update {} {
+  global umltg_state tu_ip ip2tmap
+  
+  if {[info exists tu_ip]} {
+    set told $ip2tmap($tu_ip)
+    .$told configure -background "#d9d9d9"
+    .$told configure -activebackground "#d9d9d9"
+  }
+  switch $umltg_state {
+    0 { .tu configure -background "#d9d9d9"
+        .tu configure -activebackground "#d9d9d9"
+        .tu configure -text ""
+    }
+    1 { .tu configure -background orange
+        .tu configure -activebackground orange
+    }
+  }
+}
+
+# Diversion Button callback
+proc umltg_keyRelease {} {
+  global umltg_state myipaddr t2ipmap
+
+  switch $umltg_state {
+    0 {set umltg_state 1}
+    1 {set umltg_state 0
+      # Diversion release == Diversion to myipaddr
+      foreach i {t1 t2 t3 t4 t5 t6 t7 t8} {
+        set da_ip $t2ipmap($i)
+        rsig_puts $da_ip "d $myipaddr"
+      }
+    }
+  }
+  umltg_update
+}
+
+# Direct Access Buttons callback
+proc umltg_da_keyRelease {t} {
+  global t2ipmap textmap tu_ip ip2tmap myipaddr umltg_state
+  
+  # alten Zustand deaktivieren und updaten
+  umltg_update
+ 
+  # Model variable ändern
+  set tu_ip $t2ipmap($t)
+ 
+  # neuen Zustand updaten
+  .$t configure -background orange
+  .$t configure -activebackground orange
+  set tu_text $textmap($tu_ip)
+  .tu configure -text $tu_text
+  
+  # Begin Umleitung Signalisierung [IS_41]
+  foreach i {t1 t2 t3 t4 t5 t6 t7 t8} {
+    set da_ip $t2ipmap($i)
+    rsig_puts $da_ip "d $tu_ip"
+  }
+  # End Umleitung Signalisierung [IS_41]
+}
+
+# ##############################################################
+# Direct Access / Diversion Buttons Callbacks
+
+proc keyPress {t} {
+  global umltg_state
+  
+  switch $umltg_state {
+    0 {da_keyPress $t}
+    1 {}
+  }
+}
+
+proc keyRelease {t} {
+  global umltg_state told
+  
+  switch $umltg_state {
+    0 {da_keyRelease $t}
+    1 {umltg_da_keyRelease $t}
+  }
+}
+
+# ##############################################################
+# Direct Access model relevant function
+
+proc tx_begin {ip} {
+  global ip2tmap state
+
+  set t $ip2tmap($ip)
+  #puts "tx_begin $ip $t"
+  switch $state($t) {
+  0 {set state($t) 1}
+  1 { }
+  2 {set state($t) 3}
+  3 { }
+  }
+  da_ca_update $t $state($t)
+}
+
+proc rx_begin {ip} {
+  global ip2tmap state
+
+  set t $ip2tmap($ip)
+  #puts "rx_begin $ip $t"
+  switch $state($t) {
+  0 {set state($t) 2}
+  1 {set state($t) 3}
+  2 { }
+  3 { }
+  }
+  
+  # Answer Button Req IS_14
+  global ta_ip
+  
+  set ta_ip $ip
+  ca_update
+  
+  .ta configure -command [list keyRelease $t]
+  bind .ta <ButtonPress-1> [list keyPress $t]
+  # End Answer Button Req IS_14
+  
+  da_ca_update $t $state($t) 
+}
+
+proc tx_end {ip} {
+  global ip2tmap state
+
+  set t $ip2tmap($ip)
+  #puts "tx_end $ip $t"
+  switch $state($t) {
+  0 {}
+  1 {set state($t) 0}
+  2 { }
+  3 {set state($t) 2}
+  }
+  da_ca_update $t $state($t)
+}
+
+proc rx_end {ip} {
+  global ip2tmap state
+
+  set t $ip2tmap($ip)
+  #puts "rx_end $ip $t"
+  switch $state($t) {
+  0 { }
+  1 { }
+  2 {set state($t) 0}
+  3 {set state($t) 1}
+  }
+  da_ca_update $t $state($t)
+}
+
+# ##############################################################
+# Local Signalling
+
+# intercom.tcl from own intercomd Signalling Receive
+proc lsig_recv {} {
+  global lsig_sock
+  
+  gets $lsig_sock cmd
+  # puts "lsig_recv $cmd"
+  set argv [split $cmd]
+  # puts $argv
+  set ip [lindex $argv 1]
+  switch [lindex $argv 0] {
+    c {tx_begin $ip}
+    r {rx_begin $ip}
+    h {tx_end $ip}
+    d {rx_end $ip}
+  }
+}
+
+# ##############################################################
+# Program exit (abort, close) Handler
+
+proc onDestroy {} {
+  global destroyflag lsig_sock rsig_recv_sock
+  
+  if {$destroyflag == 0} {
+    set destroyflag 1
+    puts "Terminate intercomd and intercom"
+    close $lsig_sock
+    close $rsig_recv_sock
+    exec /usr/bin/killall -9 /usr/local/bin/intercomd \
+      /usr/local/bin/intercomd1
+  }
+}
+
+# ##############################################################
+# Read configuration file - hack just use Tcl/Tk parser
+
+proc guiconfig {t text ip} {
+  global state longKey ip2tmap t2ipmap umltgmap
+  
+  set state($t) 0
+  set longKey($t) 0
+  
+  rsig_send_init $ip
+  
+  set ip2tmap($ip) $t
+  set t2ipmap($t) $ip
+  
+  set umltgmap($ip) $ip   ;# keine Umleitung
+  
+  .$t configure -text $text
+  .$t configure -command [list keyRelease $t]
+  bind .$t <ButtonPress-1> [list keyPress $t]
+  
+  # Answer Button Req IS_14
+  global textmap
+  
+  set textmap($ip) $text
+  
+  da_ca_update $t $state($t)
+}
+
+# ##############################################################
+# Begin main
+
+# init and register programm termination handler
+set destroyflag 0
+bind . <Destroy> [list onDestroy]
+
+# include GUI
+source /usr/local/bin/intercom.ui.tcl
+intercom_ui .
+
+# init model
+foreach {i} {t1 t2 t3 t4 t5 t6 t7 t8} {
+  set t_updown($i) 0
+}
+
+# init view
+foreach {i} {t1 t2 t3 t4 t5 t6 t7 t8 ta tu} {
+  .$i configure -width 5 -height 2 -highlightthickness 12
+}
+
+# init Common Answer-Button Req. IS_14
+set ta_ip ""
+
+# init and register Diversion Req. IS_41
+set umltg_state 0
+.tu configure -command [list umltg_keyRelease]
+
+# include configuration
+if {[file exists ~/.intercom.conf]} {
+  source ~/.intercom.conf
+} else {
+  file copy /usr/local/bin/intercom.conf ~/.intercom.conf
+  puts ""
+  puts "Please edit the file ~/.intercom.conf for your Labels and your"
+  puts "IP-addresses. Then start intercom again."
+  exit
+}
+
+# init local signalling to intercomd, a TCP connection
+set lsig_sock [socket 127.0.0.1 4999]
+fileevent $lsig_sock readable lsig_recv
+
+# init remote signalling to intercom.tcl, an UDP "connection"
+set rsig_recv_sock [rsig_recv_init 55004]
+
+# set window title
+set nodename [exec uname -n]
+wm title . "intercom $nodename"
+
+# hack: get my ip address
+set hostsline [exec grep $nodename /etc/hosts]
+set myipaddr [lindex [split $hostsline] 0]
+
+# End main
+# ##############################################################

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.