root/rat/trunk/ui_audiotool.tcl @ 3106

Revision 3106, 95.9 KB (checked in by ucacoxh, 14 years ago)

- Added common/ntp.h common/ntp.c which do basic ntp timestamp get, conversion,

and differencing.

- Changed rtp library to use ntp.h ntp.c.
- Add rtt calculation to rat on reception of sr with lsr != 0.
- Add fields in pdb.h for last_rtt and avg_rtt.

Still have to add field to ui and probably decide an mbus message
name, for moment it's rtp.source.rtt.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1catch {
2#
3# Copyright (c) 1995-2000 University College London
4# All rights reserved.
5#
6# $Revision$
7#
8# Full terms and conditions of the copyright appear below.
9#
10
11#wm withdraw .
12
13if {[string compare [info commands registry] "registry"] == 0} {
14    set win32 1
15} else {
16    set win32 0
17    option add *Menu*selectColor                forestgreen
18    option add *Radiobutton*selectColor         forestgreen
19    option add *Checkbutton*selectColor         forestgreen
20    option add *Entry.background                gray70
21}
22
23set statsfont     [font actual {helvetica 10}]
24set compfont      [font actual {helvetica 10}]
25set titlefont     [font actual {helvetica 10}]
26set infofont      [font actual {helvetica 10}]
27set smallfont     [font actual {helvetica  8}]
28set verysmallfont [font actual {helvetica  8}]
29
30set speaker_highlight white
31
32option add *Entry.relief       sunken
33option add *borderWidth        1
34option add *highlightThickness 0
35option add *font               $infofont
36option add *Menu*tearOff       0
37
38set V(class) "Mbone Applications"
39set V(app)   "rat"
40
41set iht                 16
42set iwd                 250
43set cancel_info_timer   0
44set num_ssrc            0
45set fw                  .l.t.list.f
46set iports             [list]
47set oports             [list]
48set bps_in              "0.0 b/s"
49set bps_out             $bps_in
50
51# Sliders use scale widget and this invokes it's -command option when
52# it is created (doh!)  We don't know what gain and volume settings
53# should be before we've received info from the audio engine.
54# Don't send our initial value if we've not heard anything from engine
55# first.  Otherwise we get catch-22 with both engine and ui queuing
56# messages of gains to each other and often UI wins, which it never
57# should do.
58
59set received(gain)      0
60set received(volume)    0
61
62###############################################################################
63#
64# Debugging Functions
65#
66###############################################################################
67
68# tvar - trace variable callback for watching changes to variables
69# e.g. to watch write events to myVar use:
70#                                          trace variable myVar w tvar
71
72proc tvar {name element op} {
73# Compose variable name and print out change
74    if {$element != ""} {
75        set name ${name}($element)
76    }
77    upvar $name x
78    puts stderr "Variable $name set to $x."
79
80# Unravel stack and display
81    puts "Stack trace:"
82    set depth [info level]
83    set l 0
84    while {$l < $depth} {
85        puts stderr "\tLevel $l: [info level $l]"
86        incr l
87    }
88}
89
90###############################################################################
91
92# trace variable gain w tvar
93
94proc init_source {ssrc} {
95        global CNAME NAME EMAIL LOC PHONE TOOL NOTE SSRC num_ssrc
96        global CODEC DURATION PCKTS_RECV PCKTS_LOST PCKTS_MISO PCKTS_DUP JITTER \
97                LOSS_TO_ME LOSS_FROM_ME INDEX JIT_TOGED BUFFER_SIZE PLAYOUT_DELAY \
98                GAIN MUTE SKEW SPIKE_EVENTS SPIKE_TOGED
99
100        # This is a debugging test -- old versions of the mbus used the
101        # cname to identify participants, whilst the newer version uses
102        # the ssrc.  This check detects if old style commands are being
103        # used and raises an error if so.
104        if [regexp {.*@[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+} "$ssrc"] {
105                error "ssrc $ssrc invalid"
106        }
107
108        if {[array names INDEX $ssrc] != [list $ssrc]} {
109                # This is a source we've not seen before...
110                set         CNAME($ssrc) ""
111                set          NAME($ssrc) $ssrc
112                set         EMAIL($ssrc) ""
113                set         PHONE($ssrc) ""
114                set           LOC($ssrc) ""
115                set          TOOL($ssrc) ""
116                set          NOTE($ssrc) ""
117                set         CODEC($ssrc) unknown
118                set          GAIN($ssrc) 1.0
119                set          MUTE($ssrc) 0
120                set      DURATION($ssrc) ""
121                set   BUFFER_SIZE($ssrc) 0
122                set PLAYOUT_DELAY($ssrc) 0
123                set          SKEW($ssrc) 1.000
124                set   SPIKE_EVENTS($ssrc) 0         
125                set   SPIKE_TOGED($ssrc) 0         
126                set    PCKTS_RECV($ssrc) 0
127                set    PCKTS_LOST($ssrc) 0
128                set    PCKTS_MISO($ssrc) 0
129                set     PCKTS_DUP($ssrc) 0
130                set        JITTER($ssrc) 0
131                set     JIT_TOGED($ssrc) 0
132                set    LOSS_TO_ME($ssrc) 0
133                set  LOSS_FROM_ME($ssrc) 0
134                set  HEARD_LOSS_TO_ME($ssrc) 0
135                set  HEARD_LOSS_FROM_ME($ssrc) 0
136                set         INDEX($ssrc) $num_ssrc
137                set          SSRC($ssrc) $ssrc
138                incr num_ssrc
139                chart_add   $ssrc
140        }
141}
142
143proc window_plist {ssrc} {
144        global fw
145        regsub -all {@|\.} $ssrc {-} foo
146        return $fw.source-$foo
147}
148
149proc window_stats {ssrc} {
150        regsub -all {[\. ]} $ssrc {-} foo
151        return .stats$foo
152}
153
154# Commands to send message over the conference bus...
155proc output_mute {state} {
156    mbus_send "R" "audio.output.mute" "$state"
157    bargraphState .r.c.rx.au.pow.bar [expr ! $state]
158}
159
160proc input_mute {state} {
161    mbus_send "R" "audio.input.mute" "$state"
162    bargraphState .r.c.tx.au.pow.bar [expr ! $state]
163}
164
165proc set_vol {new_vol} {
166    global volume received
167    set volume $new_vol
168    if {$received(volume)} {
169        mbus_send "R" "audio.output.gain" $volume
170    }
171}
172
173proc set_gain {new_gain} {
174    global gain received
175    set gain $new_gain
176    if {$received(gain)} {
177        mbus_send "R" "audio.input.gain" $gain
178    }
179}
180
181proc toggle_iport {} {
182    global iport iports
183
184    set len [llength $iports]
185# lsearch returns -1 if not found, index otherwise
186    set idx [lsearch -exact $iports $iport]
187
188    if {$idx != -1} {
189        incr idx
190        set idx [expr $idx % $len]
191        set port [lindex $iports $idx]
192        mbus_send "R" "audio.input.port" [mbus_encode_str $port]
193    }
194}
195
196proc incr_port {varname listname delta} {
197    upvar $varname  port
198    upvar $listname ports
199    set len [llength $ports]
200# lsearch returns -1 if not found, index otherwise
201    set idx [lsearch -exact $ports $port]
202   
203    if {$idx != -1} {
204        incr idx $delta
205        if {$idx < 0} {
206            set idx [expr $len - 1]
207        } elseif {$idx >= $len} {
208            set idx 0
209        }
210        set port [lindex $ports $idx]
211# yuechh!
212        if {$varname == "iport"} {
213            mbus_send "R" "audio.input.port" [mbus_encode_str $port]
214        } else {
215            mbus_send "R" "audio.output.port" [mbus_encode_str $port]
216        }
217    }
218}
219
220proc mbus_heartbeat {} {
221}
222
223#############################################################################################################
224# Reception of Mbus messages...
225
226proc mbus_recv {cmnd args} {
227        # This is not the most efficient way of doing this, since we could call mbus_recv_...
228        # directly from the C code. It does, however, make it explicit which Mbus commands we
229        # understand.
230        switch $cmnd {
231                mbus.waiting                    {eval mbus_recv_mbus.waiting $args}
232                mbus.go                         {eval mbus_recv_mbus.go $args}
233                mbus.hello                      {eval mbus_recv_mbus.hello $args}
234                mbus.quit                       {eval mbus_recv_mbus.quit $args}
235                tool.rat.sampling.supported     {eval mbus_recv_tool.rat.sampling.supported $args}
236                tool.rat.converter              {eval mbus_recv_tool.rat.converter $args}
237                tool.rat.converters.flush       {eval mbus_recv_tool.rat.converters.flush $args}
238                tool.rat.converters.add         {eval mbus_recv_tool.rat.converters.add $args}
239                tool.rat.repairs.flush          {eval mbus_recv_tool.rat.repairs.flush $args}
240                tool.rat.repairs.add            {eval mbus_recv_tool.rat.repairs.add $args}
241                tool.rat.powermeter             {eval mbus_recv_tool.rat.powermeter $args}
242                tool.rat.agc                    {eval mbus_recv_tool.rat.agc $args}
243                tool.rat.format.in              {eval mbus_recv_tool.rat.format.in $args}
244                tool.rat.codec                  {eval mbus_recv_tool.rat.codec $args}
245                tool.rat.codec.details          {eval mbus_recv_tool.rat.codec.details $args}
246                tool.rat.rate                   {eval mbus_recv_tool.rat.rate $args}
247                tool.rat.lecture.mode           {eval mbus_recv_tool.rat.lecture.mode $args}
248                tool.rat.audio.buffered         {eval mbus_recv_tool.rat.audio.buffered $args}
249                tool.rat.audio.delay            {eval mbus_recv_tool.rat.audio.delay $args}
250                tool.rat.audio.skew             {eval mbus_recv_tool.rat.audio.skew $args}
251                tool.rat.spike.events           {eval mbus_recv_tool.rat.spike.events $args}
252                tool.rat.spike.toged            {eval mbus_recv_tool.rat.spike.toged $args}
253                tool.rat.3d.enabled             {eval mbus_recv_tool.rat.3d.enabled $args}
254                tool.rat.3d.azimuth.min         {eval mbus_recv_tool.rat.3d.azimuth.min $args}
255                tool.rat.3d.azimuth.max         {eval mbus_recv_tool.rat.3d.azimuth.max $args}
256                tool.rat.3d.filter.types        {eval mbus_recv_tool.rat.3d.filter.types   $args}
257                tool.rat.3d.filter.lengths      {eval mbus_recv_tool.rat.3d.filter.lengths $args}
258                tool.rat.3d.user.settings       {eval mbus_recv_tool.rat.3d.user.settings  $args}
259                tool.rat.playout.limit          {eval mbus_recv_tool.rat.playout.limit $args}
260                tool.rat.playout.min            {eval mbus_recv_tool.rat.playout.min   $args}
261                tool.rat.playout.max            {eval mbus_recv_tool.rat.playout.max   $args}
262                tool.rat.echo.suppress          {eval mbus_recv_tool.rat.echo.suppress $args}
263                tool.rat.loopback               {eval mbus_recv_tool.rat.loopback      $args}
264                tool.rat.bps.in                 {eval mbus_recv_tool.rat.bps.in        $args}
265                tool.rat.bps.out                {eval mbus_recv_tool.rat.bps.out       $args}
266                audio.suppress.silence          {eval mbus_recv_audio.suppress.silence $args}
267                audio.channel.coding            {eval mbus_recv_audio.channel.coding $args}
268                audio.channel.repair            {eval mbus_recv_audio.channel.repair $args}
269                audio.devices.flush             {eval mbus_recv_audio_devices_flush $args}
270                audio.devices.add               {eval mbus_recv_audio_devices_add $args}
271                audio.device                    {eval mbus_recv_audio_device $args}
272                audio.input.gain                {eval mbus_recv_audio.input.gain $args}
273                audio.input.port                {eval mbus_recv_audio.input.port $args}
274                audio.input.ports.add           {eval mbus_recv_audio.input.ports.add $args}
275                audio.input.ports.flush         {eval mbus_recv_audio.input.ports.flush $args}
276                audio.input.mute                {eval mbus_recv_audio.input.mute $args}
277                audio.input.powermeter          {eval mbus_recv_audio.input.powermeter $args}
278                audio.output.gain               {eval mbus_recv_audio.output.gain $args}
279                audio.output.port               {eval mbus_recv_audio.output.port $args}
280                audio.output.ports.add          {eval mbus_recv_audio.output.ports.add $args}
281                audio.output.ports.flush        {eval mbus_recv_audio.output.ports.flush $args}
282                audio.output.mute               {eval mbus_recv_audio.output.mute $args}
283                audio.output.powermeter         {eval mbus_recv_audio.output.powermeter $args}
284                audio.file.play.ready           {eval mbus_recv_audio.file.play.ready   $args}
285                audio.file.play.alive           {eval mbus_recv_audio.file.play.alive $args}
286                audio.file.record.ready         {eval mbus_recv_audio.file.record.ready $args}
287                audio.file.record.alive         {eval mbus_recv_audio.file.record.alive $args}
288                session.title                   {eval mbus_recv_session.title $args}
289                rtp.addr                        {eval mbus_recv_rtp.addr $args}
290                rtp.ssrc                        {eval mbus_recv_rtp.ssrc $args}
291                rtp.source.exists               {eval mbus_recv_rtp.source.exists $args}
292                rtp.source.remove               {eval mbus_recv_rtp.source.remove $args}
293                rtp.source.cname                {eval mbus_recv_rtp.source.cname $args}
294                rtp.source.name                 {eval mbus_recv_rtp.source.name $args}
295                rtp.source.email                {eval mbus_recv_rtp.source.email $args}
296                rtp.source.phone                {eval mbus_recv_rtp.source.phone $args}
297                rtp.source.loc                  {eval mbus_recv_rtp.source.loc $args}
298                rtp.source.tool                 {eval mbus_recv_rtp.source.tool $args}
299                rtp.source.note                 {eval mbus_recv_rtp.source.note $args}
300                rtp.source.codec                {eval mbus_recv_rtp.source.codec $args}
301                rtp.source.packet.duration      {eval mbus_recv_rtp.source.packet.duration $args}
302                rtp.source.packet.loss          {eval mbus_recv_rtp.source.packet.loss $args}
303                rtp.source.reception            {eval mbus_recv_rtp.source.reception $args}
304                rtp.source.active               {eval mbus_recv_rtp.source.active $args}
305                rtp.source.inactive             {eval mbus_recv_rtp.source.inactive $args}
306                rtp.source.mute                 {eval mbus_recv_rtp.source.mute $args}
307                rtp.source.gain                 {eval mbus_recv_rtp.source.gain $args}
308                rtp.source.rtt                  {puts "rtt $args"}
309                security.encryption.key         {eval mbus_recv_security.encryption.key $args}
310                default                         {puts "Unknown mbus command $cmnd"}
311        }
312}
313
314proc mbus_recv_mbus.waiting {condition} {
315        if {$condition == "rat.ui.init"} {
316                mbus_send "U" "mbus.go" [mbus_encode_str rat.ui.init]
317        }
318}
319
320proc mbus_recv_mbus.go {condition} {
321}
322
323proc mbus_recv_mbus.hello {} {
324        # Ignore...
325}
326
327proc change_freq {new_freq} {
328    global freq
329
330    if {$freq != $new_freq} {
331        set freq $new_freq
332        update_channels_displayed
333        update_codecs_displayed
334        reset_encodings
335    }
336}
337
338proc change_channels {new_channels} {
339    global ichannels
340    if {$ichannels != $new_channels} {
341        set ichannels $new_channels
342        update_codecs_displayed
343        reset_encodings
344    }
345}
346
347proc update_channels_displayed {} {
348    global freq channel_support
349
350    set m1 .prefs.pane.audio.dd.sampling.ch_in.mb.m
351    $m1 delete 0 last
352    set s [lsearch -glob $channel_support *$freq*]
353   
354    foreach i [lrange [split [lindex $channel_support $s] ","] 1 2] {
355         $m1 add command -label "$i" -command "change_channels $i"
356    }
357}
358
359proc mbus_recv_tool.rat.sampling.supported {arg} {
360    global freq channel_support
361
362    #clear away old state of channel support
363    if [info exists channel_support] {
364        unset channel_support
365    }
366
367    set freqs [list]
368    set channel_support [list]
369
370    .prefs.pane.audio.dd.sampling.freq.mb.m delete 0 last
371
372    set mode [split $arg]
373    foreach m $mode {
374        lappend channel_support $m
375        set support [split $m ","]
376        set f [lindex $support 0]
377        lappend freqs $f
378        .prefs.pane.audio.dd.sampling.freq.mb.m add command -label $f -command "change_freq $f"
379    }
380    set freq [lindex $freqs 0]
381    update_channels_displayed
382}
383
384# CODEC HANDLING ##############################################################
385
386set codecs {}
387set prencs  {}
388set secencs {}
389set layerencs {}
390
391proc codec_get_name {nickname freq channels} {
392    global codecs codec_nick_name codec_rate codec_channels
393
394    foreach {c} $codecs {
395        if {$codec_nick_name($c)    == $nickname && \
396                $codec_rate($c)     == $freq && \
397                $codec_channels($c) == $channels} {
398            return $c
399        }
400    }
401}
402
403proc codecs_loosely_matching {freq channels} {
404    global codecs codec_nick_name codec_channels codec_rate codec_pt codec_state_size codec_data_size codec_block_size codec_desc
405   
406    set x {}
407
408    foreach {c} $codecs {
409        if {$codec_channels($c) == $channels && \
410        $codec_rate($c) == $freq && \
411        $codec_pt($c) != "-" } {
412            lappend x $c
413        }
414    }
415
416    return $x
417}
418
419proc codecs_matching {freq channels blocksize} {
420    global codec_block_size
421    set codecs [codecs_loosely_matching $freq $channels]
422
423    set x {}
424
425    foreach {c} $codecs {
426        if {$codec_block_size($c) == $blocksize} {
427            lappend x $c
428        }
429    }
430    return $x
431}
432
433proc mbus_recv_tool.rat.codec.details {args} {
434    catch {
435        global codecs codec_nick_name codec_channels codec_rate codec_pt codec_state_size codec_data_size codec_block_size codec_desc codec_caps codec_layers
436       
437        set name [lindex $args 1]
438        if {[lsearch $codecs $name] == -1} {
439            lappend codecs $name
440        }
441        set codec_pt($name)         [lindex $args 0]
442        set codec_nick_name($name)  [lindex $args 2]
443        set codec_channels($name)   [lindex $args 3]
444        set codec_rate($name)       [lindex $args 4]
445        set codec_block_size($name) [lindex $args 5]
446        set codec_state_size($name) [lindex $args 6]
447        set codec_data_size($name)  [lindex $args 7]
448        set codec_desc($name)       [lindex $args 8]
449        set codec_caps($name)       [lindex $args 9]
450        set codec_layers($name)         [lindex $args 10]
451        set stackup ""
452    } details_error
453
454    if { $details_error != "" } {
455        puts "Error: $details_error"
456        destroy .
457        exit -1
458    }
459}
460
461proc update_primary_list {arg} {
462    # We now have a list of codecs which this RAT supports...
463    global prenc prencs
464
465    .prefs.pane.transmission.dd.pri.m.menu delete 0 last
466    set prencs {}
467
468    set codecs [split $arg]
469    foreach c $codecs {
470        .prefs.pane.transmission.dd.pri.m.menu    add command -label $c -command "set prenc $c; update_codecs_displayed"
471        lappend prencs $c
472    }
473
474    if {[lsearch $codecs $prenc] == -1} {
475        #primary is not on list
476        set prenc [lindex $codecs 0]
477    }
478}
479
480proc update_redundancy_list {arg} {
481    global secenc secencs
482
483    .prefs.pane.transmission.cc.red.fc.m.menu delete 0 last
484    set secencs {}
485
486    set codecs [split $arg]
487    foreach c $codecs {
488        .prefs.pane.transmission.cc.red.fc.m.menu add command -label $c -command "set secenc \"$c\""
489        lappend secencs $c
490    }
491    if {[lsearch $codecs $secenc] == -1} {
492        #primary is not on list
493        set secenc [lindex $codecs 0]
494    }
495}
496
497proc update_layer_list {arg} {
498    global layerenc layerencs
499
500    .prefs.pane.transmission.cc.layer.fc.m.menu delete 0 last
501    set layerencs {}
502
503    for {set i 1} {$i <= $arg} {incr i} {
504        .prefs.pane.transmission.cc.layer.fc.m.menu add command -label $i -command "set layerenc \"$i\""
505        lappend layerencs $i
506        }
507        if {$layerenc > $arg} {
508        #new codec doesn't support as many layers
509        set layerenc $arg
510        }
511}
512
513proc reset_encodings {} {
514    global prenc prencs secenc secencs layerenc layerencs
515    set prenc  [lindex $prencs 0]
516    set secenc [lindex $secencs 0]
517        set layerenc [lindex $layerencs 0]
518}
519
520proc update_codecs_displayed { } {
521    global freq ichannels codec_nick_name prenc codec_block_size codec_caps codec_layers
522
523    if {[string match $ichannels Mono]} {
524        set sample_channels 1
525    } else {
526        set sample_channels 2
527    }
528
529    set sample_rate [string trimright $freq -kHz]
530    set sample_rate [expr $sample_rate * 1000]
531
532    set long_names [codecs_loosely_matching $sample_rate $sample_channels]
533
534    set friendly_names {}
535    foreach {n} $long_names {
536        # only interested in codecs that can (e)ncode
537        if {[string first $codec_caps($n) ncode]} {
538            lappend friendly_names $codec_nick_name($n)
539        }
540    }
541
542    update_primary_list $friendly_names
543
544    set long_name [codec_get_name $prenc $sample_rate $sample_channels]
545    set long_names [codecs_matching $sample_rate $sample_channels $codec_block_size($long_name)]
546
547    set friendly_names {}
548    set found 0
549    foreach {n} $long_names {
550        # Only display codecs of same or lower order as primary in primary list
551        if {$codec_nick_name($n) == $prenc} {
552            set found 1
553        }
554        if {$found} {
555            if {[string first $codec_caps($n) ncode]} {
556                lappend friendly_names $codec_nick_name($n)
557            }
558        }
559    }
560   
561    update_redundancy_list $friendly_names
562
563        # Assume that all codecs of one type support the same number of layers
564        foreach {n} $long_names {
565        if {$codec_nick_name($n) == $prenc} {
566        break
567        }
568        }
569        update_layer_list $codec_layers($n)
570}
571
572proc change_sampling { } {
573    update_channels_displayed
574    update_codecs_displayed
575}
576
577###############################################################################
578
579proc mbus_recv_tool.rat.converters.flush {} {
580    .prefs.pane.reception.r.ms.menu delete 0 last
581}
582
583proc mbus_recv_tool.rat.converters.add {arg} {
584    global convert_var
585    .prefs.pane.reception.r.ms.menu add command -label "$arg" -command "set convert_var \"$arg\""
586}
587
588proc mbus_recv_tool.rat.converter {arg} {
589    global convert_var
590    set convert_var $arg
591}
592
593proc mbus_recv_tool.rat.repairs.flush {} {
594    .prefs.pane.reception.r.m.menu delete 0 last
595}
596
597
598proc mbus_recv_tool.rat.repairs.add {arg} {
599    global repair_var
600    .prefs.pane.reception.r.m.menu add command -label "$arg" -command "set repair_var \"$arg\""
601}
602
603proc mbus_recv_audio_devices_flush {} {
604    .prefs.pane.audio.dd.device.mdev.menu delete 0 last
605}
606
607proc mbus_recv_audio_devices_add {arg} {
608    global audio_device
609
610    .prefs.pane.audio.dd.device.mdev.menu add command -label "$arg" -command "set audio_device \"$arg\""
611
612    set len [string length "$arg"]
613    set curr [.prefs.pane.audio.dd.device.mdev cget -width]
614
615    if {$len > $curr} {
616        .prefs.pane.audio.dd.device.mdev configure -width $len
617    }
618}
619
620proc mbus_recv_audio_device {arg} {
621        global audio_device
622        set audio_device $arg
623}
624
625proc mbus_recv_tool.rat.powermeter {arg} {
626        global meter_var
627        set meter_var $arg
628}
629
630proc mbus_recv_tool.rat.agc {arg} {
631  global agc_var
632  set agc_var $arg
633}
634
635proc mbus_recv_security.encryption.key {new_key} {
636        global key_var key
637        set key_var 1
638        set key     $new_key
639}
640
641proc mbus_recv_tool.rat.format.in {arg} {
642    global freq ichannels
643#expect arg to be <sample_type>,<sample rate>,<mono/stereo>
644    set e [split $arg ","]
645   
646    set freq      [lindex $e 1]
647    set ichannels [lindex $e 2]
648}
649
650proc mbus_recv_tool.rat.codec {arg} {
651  global prenc
652  set prenc $arg
653}
654
655proc mbus_recv_tool.rat.rate {arg} {
656    global upp
657    set upp $arg
658}
659
660proc mbus_recv_audio.channel.coding {args} {
661    global channel_var secenc red_off int_units int_gap prenc layerenc
662
663    set channel_var [lindex $args 0]
664
665    switch [string tolower $channel_var] {
666        redundancy {
667                set secenc  [lindex $args 1]
668                set red_off [lindex $args 2]
669        }
670        interleaved {
671                set int_units [lindex $args 1]
672                set int_gap   [lindex $args 2]
673        }
674        layering {
675#               should we be playing with primary encoding?
676#               set prenc         [lindex $args 1]
677                set layerenc  [lindex $args 2]
678        }
679    }
680}
681
682proc mbus_recv_audio.channel.repair {arg} {
683  global repair_var
684  set repair_var $arg
685}
686
687proc mbus_recv_audio.input.powermeter {level} {
688        global bargraphTotalHeight
689        bargraphSetHeight .r.c.tx.au.pow.bar [expr ($level * $bargraphTotalHeight) / 100]
690}
691
692proc mbus_recv_audio.output.powermeter {level} {
693        global bargraphTotalHeight
694        bargraphSetHeight .r.c.rx.au.pow.bar  [expr ($level * $bargraphTotalHeight) / 100]
695}
696
697proc mbus_recv_audio.input.gain {new_gain} {
698    global received gain
699    set received(gain) 1
700    set gain $new_gain
701}
702
703proc mbus_recv_audio.input.ports.flush {} {
704    global iports
705    set iports [list]
706}
707
708proc mbus_recv_audio.input.ports.add {port} {
709    global iports
710    lappend iports "$port"
711}
712
713proc mbus_recv_audio.input.port {port} {
714    global iport
715    set    iport $port
716}
717
718proc mbus_recv_audio.input.mute {val} {
719    global in_mute_var
720    set in_mute_var $val
721    bargraphState .r.c.tx.au.pow.bar [expr ! $val]
722}
723
724proc mbus_recv_audio.output.gain {new_gain} {
725    global received volume
726    set received(volume) 1
727    set volume $new_gain
728}
729
730proc mbus_recv_audio.output.port {port} {
731    global oport
732    set oport $port
733}
734
735proc mbus_recv_audio.output.ports.flush {} {
736    global oports
737    set oports [list]
738}
739
740proc mbus_recv_audio.output.ports.add {port} {
741    global oports
742    lappend oports "$port"
743}
744
745proc mbus_recv_audio.output.mute {val} {
746    global out_mute_var
747    set out_mute_var $val
748}
749
750proc mbus_recv_session.title {title} {
751    global session_title
752    set session_title \"$title\"
753    wm title . "RAT: $title"
754}
755
756proc mbus_recv_rtp.addr {addr rx_port tx_port ttl} {
757    global session_address group_addr
758    set group_addr $addr
759    set session_address "Address: $addr Port: $rx_port TTL: $ttl"
760}
761
762proc mbus_recv_tool.rat.lecture.mode {mode} {
763        global lecture_var
764        set lecture_var $mode
765}
766
767proc mbus_recv_audio.suppress.silence {mode} {
768        global silence_var
769        set silence_var $mode
770}
771
772proc mbus_recv_rtp.ssrc {ssrc} {
773        global my_ssrc
774
775        set my_ssrc $ssrc
776        init_source $ssrc
777        ssrc_update $ssrc
778#        puts "Got my_ssrc $ssrc"
779}
780
781proc mbus_recv_rtp.source.exists {ssrc} {
782        init_source $ssrc
783        chart_add $ssrc
784        ssrc_update $ssrc
785}
786
787proc mbus_recv_rtp.source.cname {ssrc cname} {
788        global CNAME NAME SSRC
789        init_source $ssrc
790        set CNAME($ssrc) $cname
791        if {[string compare $NAME($ssrc) $SSRC($ssrc)] == 0} {
792                set NAME($ssrc) $cname
793        }
794        chart_label $ssrc $NAME($ssrc)
795        ssrc_update $ssrc
796}
797
798proc mbus_recv_rtp.source.name {ssrc name} {
799        global NAME
800        init_source $ssrc
801        set NAME($ssrc) $name
802        chart_label $ssrc $name
803        ssrc_update $ssrc
804}
805
806proc mbus_recv_rtp.source.email {ssrc email} {
807        global EMAIL
808        init_source $ssrc
809        set EMAIL($ssrc) $email
810}
811
812proc mbus_recv_rtp.source.phone {ssrc phone} {
813        global PHONE
814        init_source $ssrc
815        set PHONE($ssrc) $phone
816}
817
818proc mbus_recv_rtp.source.loc {ssrc loc} {
819        global LOC
820        init_source $ssrc
821        set LOC($ssrc) $loc
822}
823
824proc mbus_recv_rtp.source.tool {ssrc tool} {
825        global TOOL my_ssrc tool_name
826        init_source $ssrc
827        set TOOL($ssrc) $tool
828        if {[info exists my_ssrc] && [string compare $ssrc $my_ssrc] == 0} {
829            global tool_name
830            # tool name looks like RAT x.x.x platform ....
831            # lose the platform stuff
832            set tool_frag [split $tool]
833            set tool_name "UCL [lindex $tool_frag 0] [lindex $tool_frag 1]"
834        }
835}
836
837proc mbus_recv_rtp.source.note {ssrc note} {
838        global NOTE
839        init_source $ssrc
840        set NOTE($ssrc) $note
841}
842
843
844proc mbus_recv_rtp.source.codec {ssrc codec} {
845        global CODEC
846        init_source $ssrc
847        set CODEC($ssrc) $codec
848}
849
850proc mbus_recv_rtp.source.gain {ssrc gain} {
851        global GAIN
852        init_source $ssrc
853        set GAIN($ssrc) $gain
854}
855
856proc mbus_recv_rtp.source.packet.duration {ssrc packet_duration} {
857        global DURATION
858        init_source $ssrc
859        set DURATION($ssrc) $packet_duration
860}
861
862proc mbus_recv_tool.rat.audio.buffered {ssrc buffered} {
863        global BUFFER_SIZE
864        init_source $ssrc
865        set BUFFER_SIZE($ssrc) $buffered
866}
867
868proc mbus_recv_tool.rat.audio.delay {ssrc len} {
869        global PLAYOUT_DELAY
870        init_source $ssrc
871        set PLAYOUT_DELAY($ssrc) $len
872}
873
874proc mbus_recv_tool.rat.audio.skew {ssrc skew} {
875        global SKEW
876        init_source $ssrc
877        set SKEW($ssrc) [format "%.3f" $skew]
878}
879
880proc mbus_recv_tool.rat.spike.events {ssrc events} {
881    global SPIKE_EVENTS
882    init_source $ssrc
883    set SPIKE_EVENTS($ssrc) $events
884}
885
886proc mbus_recv_tool.rat.spike.toged {ssrc toged} {
887    global SPIKE_TOGED
888    init_source $ssrc
889    set SPIKE_TOGED($ssrc) $toged
890}
891
892proc mbus_recv_tool.rat.3d.enabled {mode} {
893        global 3d_audio_var
894        set 3d_audio_var $mode
895}
896
897proc mbus_recv_tool.rat.3d.azimuth.min {min} {
898    global 3d_azimuth
899    set 3d_azimuth(min) $min
900}
901
902proc mbus_recv_tool.rat.3d.azimuth.max {max} {
903    global 3d_azimuth
904    set 3d_azimuth(max) $max
905}
906
907proc mbus_recv_tool.rat.3d.filter.types {args} {
908    global 3d_filters
909    set 3d_filters [split $args ","]
910}
911
912proc mbus_recv_tool.rat.3d.filter.lengths {args} {
913    global 3d_filter_lengths
914    set 3d_filter_lengths [split $args ","]
915}
916
917proc mbus_recv_tool.rat.3d.user.settings {args} {
918    global filter_type filter_length azimuth
919    set ssrc                 [lindex $args 0]
920    set filter_type($ssrc)   [lindex $args 1]
921    set filter_length($ssrc) [lindex $args 2]
922    set azimuth($ssrc)       [lindex $args 3]
923}
924
925proc mbus_recv_rtp.source.packet.loss {dest srce loss} {
926        global my_ssrc LOSS_FROM_ME LOSS_TO_ME HEARD_LOSS_FROM_ME HEARD_LOSS_TO_ME
927        init_source $srce
928        init_source $dest
929        chart_set $srce $dest $loss
930        if {[string compare $dest $my_ssrc] == 0} {
931                set LOSS_TO_ME($srce) $loss
932                set HEARD_LOSS_TO_ME($srce) 1
933        }
934        if {[string compare $srce $my_ssrc] == 0} {
935                set LOSS_FROM_ME($dest) $loss
936                set HEARD_LOSS_FROM_ME($dest) 1
937        }
938        ssrc_update $srce
939        ssrc_update $dest
940}
941
942proc mbus_recv_rtp.source.reception {ssrc packets_recv packets_lost packets_miso packets_dup jitter jit_tog} {
943        global PCKTS_RECV PCKTS_LOST PCKTS_MISO PCKTS_DUP JITTER JIT_TOGED
944        init_source $ssrc
945        set PCKTS_RECV($ssrc) $packets_recv
946        set PCKTS_LOST($ssrc) $packets_lost
947        set PCKTS_MISO($ssrc) $packets_miso
948        set PCKTS_DUP($ssrc)  $packets_dup
949        set JITTER($ssrc) $jitter
950        set JIT_TOGED($ssrc) $jit_tog
951}
952
953proc mbus_recv_rtp.source.active {ssrc} {
954        global speaker_highlight
955        init_source $ssrc
956        ssrc_update $ssrc
957        [window_plist $ssrc] configure -background $speaker_highlight
958}
959
960proc mbus_recv_rtp.source.inactive {ssrc} {
961        init_source $ssrc
962        ssrc_update $ssrc
963        [window_plist $ssrc] configure -background [.l.t.list cget -bg]
964}
965
966proc mbus_recv_rtp.source.remove {ssrc} {
967    global CNAME NAME EMAIL LOC PHONE TOOL NOTE CODEC DURATION PCKTS_RECV PCKTS_LOST PCKTS_MISO \
968            PCKTS_DUP JITTER BUFFER_SIZE PLAYOUT_DELAY LOSS_TO_ME LOSS_FROM_ME INDEX JIT_TOGED \
969            num_ssrc loss_to_me_timer loss_from_me_timer GAIN MUTE HEARD_LOSS_TO_ME HEARD_LOSS_FROM_ME \
970            SKEW SPIKE_EVENTS SPIKE_TOGED
971
972    # Disable updating of loss diamonds. This has to be done before we destroy the
973    # window representing the participant, else the background update may try to
974    # access a window which has been destroyed...
975    catch {after cancel $loss_to_me_timer($ssrc)}
976    catch {after cancel $loss_from_me_timer($ssrc)}
977   
978    chart_remove $ssrc
979
980    catch [destroy [window_plist $ssrc]]
981    if { [info exists CNAME($ssrc)] } {
982        unset CNAME($ssrc) NAME($ssrc) EMAIL($ssrc) PHONE($ssrc) LOC($ssrc) TOOL($ssrc) NOTE($ssrc)
983        unset CODEC($ssrc) DURATION($ssrc) PCKTS_RECV($ssrc) PCKTS_LOST($ssrc) PCKTS_MISO($ssrc) PCKTS_DUP($ssrc)
984        unset JITTER($ssrc) LOSS_TO_ME($ssrc) LOSS_FROM_ME($ssrc) INDEX($ssrc) JIT_TOGED($ssrc) BUFFER_SIZE($ssrc)
985        unset PLAYOUT_DELAY($ssrc) GAIN($ssrc) MUTE($ssrc) SKEW($ssrc) SPIKE_EVENTS($ssrc) SPIKE_TOGED($ssrc)
986        incr num_ssrc -1
987    }
988    if { [info exists HEARD_LOSS_TO_ME($ssrc)] } {
989        unset HEARD_LOSS_TO_ME($ssrc)
990    }
991    if { [info exists HEARD_LOSS_FROM_ME($ssrc)] } {
992        unset HEARD_LOSS_FROM_ME($ssrc)
993    }
994    set stats_win [window_stats $ssrc]
995    if { [winfo exists $stats_win] } {
996        destroy $stats_win
997    }
998}
999
1000proc mbus_recv_rtp.source.mute {ssrc val} {
1001        global iht MUTE
1002        set MUTE($ssrc) $val
1003        if {$val} {
1004                [window_plist $ssrc] create line [expr $iht + 2] [expr $iht / 2] 500 [expr $iht / 2] -tags a -width 2.0 -fill gray95
1005        } else {
1006                catch [[window_plist $ssrc] delete a]
1007        }
1008}
1009
1010proc mbus_recv_audio.file.play.ready {name} {
1011    global play_file
1012    set    play_file(name) $name
1013
1014    if {$play_file(state) != "play"} {
1015        file_enable_play
1016    }
1017}
1018
1019proc mbus_recv_audio.file.play.alive {alive} {
1020   
1021    global play_file
1022
1023    if {$alive} {
1024        after 200 file_play_live
1025    } else {
1026        set play_file(state) end
1027        file_enable_play
1028    }
1029}
1030
1031proc mbus_recv_audio.file.record.ready {name} {
1032    global rec_file
1033    set    rec_file(name) $name
1034    if {$rec_file(state) != "record"} {
1035        file_enable_record
1036    }
1037}
1038
1039proc mbus_recv_audio.file.record.alive {alive} {
1040        global rec_file
1041        if {$alive} {
1042                after 200 file_rec_live
1043        } else {
1044                set rec_file(state) end
1045                file_enable_record                                         
1046        }
1047}
1048
1049proc mbus_recv_tool.rat.playout.limit {e} {
1050    global limit_var
1051    set limit_var $e
1052}
1053
1054proc mbus_recv_tool.rat.playout.min {l} {
1055    global min_var
1056    set min_var $l
1057}
1058
1059proc mbus_recv_tool.rat.playout.max {u} {
1060    global max_var
1061    set max_var $u
1062}
1063
1064proc mbus_recv_tool.rat.echo.suppress {e} {
1065    global echo_var
1066    set echo_var $e
1067}
1068
1069proc mbus_recv_tool.rat.loopback {l} {
1070    global audio_loop_var
1071    set audio_loop_var $l
1072}
1073
1074proc format_bps {bps} {
1075    if {$bps < 999} {
1076        set s "b/s"
1077    } elseif {$bps < 999999} {
1078        set s "kb/s"
1079        set bps [expr $bps / 1000.0]
1080    } else {
1081        set s "Mb/s"
1082        set bps [expr $bps / 1000000.0]
1083    }
1084    return [format "%.1f %s" $bps $s]
1085}
1086
1087proc mbus_recv_tool.rat.bps.in {bps} {
1088    global bps_in
1089    set    bps_in [format_bps $bps]
1090}
1091
1092proc mbus_recv_tool.rat.bps.out {bps} {
1093    global bps_out
1094    set    bps_out [format_bps $bps]
1095}
1096
1097proc mbus_recv_mbus.quit {} {
1098        destroy .
1099}
1100
1101#############################################################################################################
1102
1103proc set_loss_to_me {ssrc loss} {
1104        global prev_loss_to_me loss_to_me_timer
1105
1106        catch {after cancel $loss_to_me_timer($ssrc)}
1107        set loss_to_me_timer($ssrc) [after 7500 catch \"[window_plist $ssrc] itemconfigure h -fill grey\"]
1108
1109        if {$loss < 5} {
1110                catch [[window_plist $ssrc] itemconfigure m -fill green]
1111        } elseif {$loss < 10} {
1112                catch [[window_plist $ssrc] itemconfigure m -fill orange]
1113        } elseif {$loss <= 100} {
1114                catch [[window_plist $ssrc] itemconfigure m -fill red]
1115        } else {
1116                catch [[window_plist $ssrc] itemconfigure m -fill grey]
1117        }
1118}
1119
1120proc set_loss_from_me {ssrc loss} {
1121        global prev_loss_from_me loss_from_me_timer
1122
1123        catch {after cancel $loss_from_me_timer($ssrc)}
1124        set loss_from_me_timer($ssrc) [after 7500 catch \"[window_plist $ssrc] itemconfigure h -fill grey\"]
1125
1126        if {$loss < 5} {
1127                catch [[window_plist $ssrc] itemconfigure h -fill green]
1128        } elseif {$loss < 10} {
1129                catch [[window_plist $ssrc] itemconfigure h -fill orange]
1130        } elseif {$loss <= 100} {
1131                catch [[window_plist $ssrc] itemconfigure h -fill red]
1132        } else {
1133                catch [[window_plist $ssrc] itemconfigure h -fill grey]
1134        }
1135}
1136
1137proc ssrc_update {ssrc} {
1138        # This procedure updates the on-screen representation of
1139        # a participant.
1140        global NAME LOSS_TO_ME LOSS_FROM_ME HEARD_LOSS_FROM_ME HEARD_LOSS_TO_ME
1141        global fw iht iwd my_ssrc
1142
1143        set cw [window_plist $ssrc]
1144
1145        if {[winfo exists $cw]} {
1146                $cw itemconfigure t -text $NAME($ssrc)
1147        } else {
1148                # Add this participant to the list...
1149                set thick 0
1150                set l $thick
1151                set h [expr $iht / 2 + $thick]
1152                set f [expr $iht + $thick]
1153                canvas $cw -width $iwd -height $f -highlightthickness $thick
1154                $cw create text [expr $f + 2] $h -anchor w -text $NAME($ssrc) -fill black -tag t
1155                $cw create polygon $l $h $h $l $h $f -outline black -fill grey -tag m
1156                $cw create polygon $f $h $h $l $h $f -outline black -fill grey -tag h
1157
1158                bind $cw <Button-1>         "toggle_stats \"$ssrc\""
1159                bind $cw <Button-2>         "toggle_mute $cw \"$ssrc\""
1160                bind $cw <Control-Button-1> "toggle_mute $cw \"$ssrc\""
1161
1162                if {[info exists my_ssrc] && ([string compare $ssrc $my_ssrc] == 0) && ([pack slaves $fw] != "")} {
1163                        pack $cw -before [lindex [pack slaves $fw] 0] -fill x
1164                }
1165                pack $cw -fill x
1166                fix_scrollbar
1167        }
1168
1169        if {[info exists HEARD_LOSS_TO_ME($ssrc)] && $HEARD_LOSS_TO_ME($ssrc) && $ssrc != $my_ssrc} {
1170            set_loss_to_me $ssrc $LOSS_TO_ME($ssrc)
1171        }
1172        if {[info exists HEARD_LOSS_FROM_ME($ssrc)] && $HEARD_LOSS_FROM_ME($ssrc) && $ssrc != $my_ssrc} {
1173            set_loss_from_me $ssrc $LOSS_FROM_ME($ssrc)
1174        }
1175}
1176
1177#power meters
1178
1179# Colors
1180set bargraphLitColors [list #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #00cc00 #2ccf00 #58d200 #84d500 #b0d800 #dddd00 #ddb000 #dd8300 #dd5600 #dd2900]
1181
1182set bargraphUnlitColors [list #006600 #006600 #006600 #006600 #006600 #006600 #006600 #006600 #006600 #006600 #006600 #006600 #166700 #2c6900 #426a00 #586c00 #6e6e00 #6e5800 #6e4100 #6e2b00 #6e1400]
1183set bargraphTotalHeight [llength $bargraphLitColors]
1184
1185proc bargraphCreate {bgraph} {
1186        global oh$bgraph bargraphTotalHeight bargraphUnlitColors
1187
1188        frame $bgraph -bd 0 -bg black
1189        for {set i 0} {$i < $bargraphTotalHeight} {incr i} {
1190                frame $bgraph.inner$i -bg "[lindex $bargraphUnlitColors $i]" -width 4 -height 6
1191                pack $bgraph.inner$i -side left -fill both -expand true -padx 1 -pady 1
1192        }
1193        set oh$bgraph 0
1194}
1195
1196proc bargraphSetHeight {bgraph height} {
1197        upvar #0 oh$bgraph oh
1198        global bargraphTotalHeight bargraphLitColors bargraphUnlitColors
1199
1200        if {$oh > $height} {
1201                for {set i [expr $height]} {$i <= $oh} {incr i} {
1202                        $bgraph.inner$i config -bg "[lindex $bargraphUnlitColors $i]"
1203                }
1204        } else {
1205            for {set i [expr $oh]} {$i <= $height} {incr i} {
1206                $bgraph.inner$i config -bg  "[lindex $bargraphLitColors $i]"
1207            }
1208        }
1209        set oh $height
1210}
1211
1212proc bargraphState {bgraph state} {
1213    upvar #0 oh$bgraph oh
1214    if {[winfo exists $bgraph]} {
1215        global bargraphTotalHeight bargraphUnlitColors
1216        if {$state} {
1217            for { set i 0 } { $i < $bargraphTotalHeight} {incr i} {
1218                $bgraph.inner$i config -bg "[lindex $bargraphUnlitColors $i]"
1219            }
1220        } else {
1221            for { set i 0 } { $i < $bargraphTotalHeight} {incr i} {
1222                $bgraph.inner$i config -bg black
1223            }
1224        }
1225    }
1226    set oh 0
1227}
1228
1229proc toggle {varname} {
1230    upvar 1 $varname local
1231    set local [expr !$local]
1232}
1233
1234proc toggle_plist {} {
1235        global plist_on
1236        if {$plist_on} {
1237                pack .l.t  -side top -fill both -expand 1 -padx 2
1238        } else {
1239                pack forget .l.t
1240        }
1241        update
1242        wm deiconify .
1243}
1244
1245proc toggle_mute {cw ssrc} {
1246        global iht
1247        if {[$cw gettags a] == ""} {
1248                mbus_send "R" "rtp.source.mute" "[mbus_encode_str $ssrc] 1"
1249        } else {
1250                mbus_send "R" "rtp.source.mute" "[mbus_encode_str $ssrc] 0"
1251        }
1252}
1253
1254proc send_gain_and_mute {ssrc} {
1255        global GAIN MUTE
1256        mbus_send "R" "rtp.source.gain" "[mbus_encode_str $ssrc] $GAIN($ssrc)"
1257        mbus_send "R" "rtp.source.mute" "[mbus_encode_str $ssrc] $MUTE($ssrc)"
1258}
1259
1260proc fix_scrollbar {} {
1261        global iht iwd fw
1262
1263        set ch [expr $iht * ([llength [pack slaves $fw]] + 2)]
1264        set bh [winfo height .l.t.scr]
1265        if {$ch > $bh} {set h $ch} else {set h $bh}
1266        .l.t.list configure -scrollregion "0.0 0.0 $iwd $h"
1267}
1268
1269proc info_timer {} {
1270        global cancel_info_timer
1271        if {$cancel_info_timer == 1} {
1272                set cancel_info_timer 0
1273        } else {
1274                update_rec_info
1275                after 1000 info_timer
1276        }
1277}
1278
1279proc stats_add_field {widget label watchVar} {
1280    global statsfont
1281    frame $widget
1282    label $widget.l -text $label -font $statsfont -anchor w
1283    label $widget.w -textvariable $watchVar -font $statsfont
1284    pack $widget -side top -fill x -anchor n
1285    pack $widget.l -side left  -fill x -expand 1
1286    pack $widget.w -side right
1287}
1288
1289proc ssrc_set_gain {ssrc gain} {
1290    global GAIN
1291    set    GAIN($ssrc) [format "%.2f " [expr pow (2, $gain)]]
1292    send_gain_and_mute $ssrc
1293}
1294
1295set 3d_azimuth(min) 0
1296set 3d_azimuth(max) 0
1297set 3d_filters        [list "Not Available"]
1298set 3d_filter_lengths [list "0"]
1299
1300proc toggle_stats {ssrc} {
1301    global statsfont
1302    set win [window_stats $ssrc]
1303    if {[winfo exists $win]} {
1304        destroy $win
1305    } else {
1306        global stats_pane
1307        # Window does not exist so create it
1308        toplevel $win 
1309        frame $win.mf
1310        pack $win.mf -padx 0 -pady 0
1311        label $win.mf.l -text "Category:"
1312       
1313        menubutton $win.mf.mb -menu $win.mf.mb.menu -indicatoron 1 -textvariable stats_pane($win) -relief raised -width 16
1314        pack $win.mf.l $win.mf.mb -side left
1315        menu $win.mf.mb.menu -tearoff 0
1316        $win.mf.mb.menu add command -label "Personal Details" -command "set_pane stats_pane($win) $win.df \"Personal Details\""
1317        $win.mf.mb.menu add command -label "Playout"          -command "set_pane stats_pane($win) $win.df Playout"
1318        $win.mf.mb.menu add command -label "Decoder"          -command "set_pane stats_pane($win) $win.df Decoder"
1319        $win.mf.mb.menu add command -label "Audio"            -command "set_pane stats_pane($win) $win.df Audio"
1320        $win.mf.mb.menu add command -label "3D Positioning"   -command "set_pane stats_pane($win) $win.df \"3D Positioning\""
1321
1322        set stats_pane($win) "Personal Details"
1323        frame $win.df
1324        frame $win.df.personal -relief groove -bd 2
1325        pack  $win.df -side top -anchor n -expand 1 -fill both
1326        pack $win.df.personal -expand 1 -fill both
1327
1328        global NAME EMAIL PHONE LOC NOTE CNAME TOOL SSRC
1329        stats_add_field $win.df.personal.1 "Name: "     NAME($ssrc)
1330        stats_add_field $win.df.personal.2 "Email: "    EMAIL($ssrc)
1331        stats_add_field $win.df.personal.3 "Phone: "    PHONE($ssrc)
1332        stats_add_field $win.df.personal.4 "Location: " LOC($ssrc)
1333        stats_add_field $win.df.personal.5 "Note: "     NOTE($ssrc)
1334        stats_add_field $win.df.personal.6 "Tool: "     TOOL($ssrc)
1335        stats_add_field $win.df.personal.7 "CNAME: "    CNAME($ssrc)
1336        stats_add_field $win.df.personal.8 "SSRC: "     SSRC($ssrc)
1337
1338        frame $win.df.playout -relief groove -bd 2
1339        global BUFFER_SIZE PLAYOUT_DELAY JITTER JIT_TOGED SKEW
1340        stats_add_field $win.df.playout.1 "Actual Playout (ms): "     BUFFER_SIZE($ssrc)
1341        stats_add_field $win.df.playout.2 "Target Playout (ms): "     PLAYOUT_DELAY($ssrc)
1342        stats_add_field $win.df.playout.3 "Arrival jitter (ms): "     JITTER($ssrc)
1343        stats_add_field $win.df.playout.4 "Packets dropped (jitter):" JIT_TOGED($ssrc)
1344        stats_add_field $win.df.playout.5 "Spike Events:"             SPIKE_EVENTS($ssrc)
1345        stats_add_field $win.df.playout.6 "Packets dropped (spike):"  SPIKE_TOGED($ssrc)
1346        stats_add_field $win.df.playout.7 "Relative clock rate:"      SKEW($ssrc)
1347
1348        frame $win.df.decoder -relief groove -bd 2
1349        global CODEC DURATION PCKTS_RECV PCKTS_LOST PCKTS_MISO \
1350               PCKTS_DUP LOSS_FROM_ME LOSS_TO_ME
1351        stats_add_field $win.df.decoder.1 "Audio encoding: "         CODEC($ssrc)
1352        stats_add_field $win.df.decoder.2 "Packet duration (ms): "   DURATION($ssrc)
1353        stats_add_field $win.df.decoder.3 "Loss from me (%): "       LOSS_FROM_ME($ssrc)
1354        stats_add_field $win.df.decoder.4 "Loss to me (%): "         LOSS_TO_ME($ssrc)
1355        stats_add_field $win.df.decoder.5 "Packets received: "       PCKTS_RECV($ssrc)
1356        stats_add_field $win.df.decoder.6 "Packets lost: "           PCKTS_LOST($ssrc)
1357        stats_add_field $win.df.decoder.7 "Packets misordered: "     PCKTS_MISO($ssrc)
1358        stats_add_field $win.df.decoder.8 "Packets duplicated: "     PCKTS_DUP($ssrc)
1359
1360# Audio settings
1361        global GAIN MUTE
1362        frame $win.df.audio -relief groove -bd 2
1363        label $win.df.audio.advice -text "The signal from the participant can\nbe scaled and muted with the controls below."
1364        pack  $win.df.audio.advice
1365
1366        checkbutton $win.df.audio.mute -text "Mute" -variable MUTE($ssrc) -command "send_gain_and_mute $ssrc"
1367        pack $win.df.audio.mute
1368
1369        frame $win.df.audio.opts
1370        pack  $win.df.audio.opts -side top
1371        label $win.df.audio.opts.title -text "Gain"
1372        scale $win.df.audio.opts.gain_scale -showvalue 0 -orient h -from -3 -to +3 -resolution 0.25 -command "ssrc_set_gain $ssrc"
1373        label $win.df.audio.opts.gain_text -textvariable GAIN($ssrc) -width 4
1374        pack  $win.df.audio.opts.title $win.df.audio.opts.gain_scale $win.df.audio.opts.gain_text -side left
1375
1376        $win.df.audio.opts.gain_scale set [expr log10($GAIN($ssrc)) / log10(2)]
1377
1378        button $win.df.audio.default -text "Default" -command "set MUTE($ssrc) 0; $win.df.audio.opts.gain_scale set 0.0; send_gain_and_mute $ssrc" 
1379        pack   $win.df.audio.default -side bottom  -anchor e -padx 2 -pady 2
1380
1381# 3D settings
1382        # Trigger engine to send details for this participant
1383        mbus_send "R" "tool.rat.3d.user.settings.request" [mbus_encode_str $ssrc]
1384
1385        frame $win.df.3d -relief groove -bd 2
1386        label $win.df.3d.advice -text "These options allow the rendering of the\nparticipant to be altered when 3D\nrendering is enabled."
1387        checkbutton $win.df.3d.ext -text "3D Audio Rendering" -variable 3d_audio_var
1388        pack $win.df.3d.advice
1389        pack $win.df.3d.ext
1390
1391        frame $win.df.3d.opts
1392        pack $win.df.3d.opts -side top
1393
1394        frame $win.df.3d.opts.filters
1395        label $win.df.3d.opts.filters.l -text "Filter Type:"
1396        pack $win.df.3d.opts.filters.l -side left -fill x -expand 1 -anchor n
1397        global 3d_filters 3d_filter_lengths
1398       
1399        global filter_type
1400        set filter_type($ssrc) [lindex $3d_filters 0]
1401
1402        set cnt 0
1403        foreach i $3d_filters {
1404            radiobutton $win.df.3d.opts.filters.$cnt \
1405                    -value "$i" -variable filter_type($ssrc) \
1406                    -text "$i"
1407                pack $win.df.3d.opts.filters.$cnt -side top -anchor w
1408            incr cnt
1409        }
1410
1411        frame $win.df.3d.opts.lengths
1412        label $win.df.3d.opts.lengths.l -text "Length:"
1413        pack $win.df.3d.opts.lengths.l -side left -fill x -expand 1 -anchor n
1414       
1415        global filter_length
1416        set filter_length($ssrc) [lindex $3d_filter_lengths 0]
1417       
1418        set cnt 0
1419        foreach i $3d_filter_lengths {
1420            radiobutton $win.df.3d.opts.lengths.$cnt \
1421                    -value "$i" -variable filter_length($ssrc) \
1422                    -text "$i"
1423            pack $win.df.3d.opts.lengths.$cnt -side top -anchor w
1424            incr cnt
1425        }
1426        pack $win.df.3d.opts.filters -side left -expand 1 -anchor n -fill x
1427        pack $win.df.3d.opts.lengths -side right -expand 1 -anchor n -fill x
1428       
1429        global 3d_azimuth azimuth
1430        frame $win.df.3d.azi
1431        label $win.df.3d.azi.lab -text "Azimuth:"
1432        scale $win.df.3d.azi.sca -from $3d_azimuth(min) -to $3d_azimuth(max) \
1433                -orient horizontal -variable azimuth($ssrc)
1434        pack  $win.df.3d.azi
1435        pack $win.df.3d.azi.lab $win.df.3d.azi.sca -side left
1436
1437        button $win.df.3d.apply -text "Apply" -command "3d_send_parameters $ssrc"
1438        pack   $win.df.3d.apply -side bottom  -anchor e -padx 2 -pady 2
1439
1440# Window Magic
1441        frame  $win.dis
1442        button $win.dis.b -text "Dismiss" -command "destroy $win; 3d_delete_parameters $ssrc"
1443        pack   $win.dis   -side bottom -anchor e
1444        pack   $win.dis.b -side right -anchor e -padx 2 -pady 2
1445        wm title $win "Participant $NAME($ssrc)"
1446#       wm resizable $win 1 1
1447        constrain_window $win $statsfont 36 24
1448    }
1449}
1450
1451proc 3d_send_parameters {ssrc} {
1452    global azimuth filter_type filter_length 3d_audio_var
1453
1454    mbus_send "R" "tool.rat.3d.enabled"   $3d_audio_var
1455    mbus_send "R" "tool.rat.3d.user.settings" "[mbus_encode_str $ssrc] [mbus_encode_str $filter_type($ssrc)] $filter_length($ssrc) $azimuth($ssrc)"
1456}
1457
1458proc 3d_delete_parameters {ssrc} {
1459    global filter_type filter_length azimuth
1460   
1461# None of these should ever fail, but you can't be too defensive...
1462    catch {
1463        unset filter_type($ssrc)
1464        unset filter_length($ssrc)
1465        unset azimuth($ssrc)
1466    }
1467}
1468
1469proc do_quit {} {
1470        catch {
1471                profile off pdat
1472                profrep pdat cpu
1473        }
1474        destroy .
1475}
1476
1477# Initialise RAT MAIN window
1478frame .r
1479frame .l
1480frame .l.t -relief groove -bd 2
1481scrollbar .l.t.scr -relief flat -highlightthickness 0 -command ".l.t.list yview"
1482canvas .l.t.list -highlightthickness 0 -bd 0 -relief flat -width $iwd -height 120 -yscrollcommand ".l.t.scr set" -yscrollincrement $iht
1483frame .l.t.list.f -highlightthickness 0 -bd 0
1484.l.t.list create window 0 0 -anchor nw -window .l.t.list.f
1485
1486frame .l.f -relief groove -bd 2
1487label .l.f.title -bd 0 -textvariable session_title -justify center
1488label .l.f.addr  -bd 0 -textvariable session_address
1489
1490frame  .st -bd 0
1491label  .st.tool -textvariable tool_name -font $infofont -justify center -pady 0
1492button .st.opts  -text "Options"   -command {wm deiconify .prefs; update_user_panel; raise .prefs}
1493button .st.about -text "About"     -command {jiggle_credits; wm deiconify .about}
1494button .st.quit  -text "Quit"      -command do_quit
1495
1496frame .r.c -bd 0
1497frame .r.c.rx -relief groove -bd 2
1498frame .r.c.tx -relief groove -bd 2
1499
1500pack .st -side bottom -fill x -padx 2 -pady 0
1501pack .st.tool -side left -fill both -expand 1
1502
1503pack .st.quit .st.about .st.opts -side right -anchor w -padx 2 -pady 2
1504
1505pack .r -side top -fill x -padx 2
1506pack .r.c -side top -fill x -expand 1
1507pack .r.c.rx -side left -fill x -expand 1
1508pack .r.c.tx -side left -fill x -expand 1
1509
1510pack .l -side top -fill both -expand 1
1511pack .l.f -side bottom -fill x -padx 2 -pady 2
1512pack .l.f.title .l.f.addr -side top -pady 2 -anchor w -fill x
1513pack .l.t  -side top -fill both -expand 1 -padx 2
1514pack .l.t.scr -side left -fill y
1515pack .l.t.list -side left -fill both -expand 1
1516bind .l.t.list <Configure> {fix_scrollbar}
1517
1518# Device output controls
1519set out_mute_var 0
1520frame .r.c.rx.net
1521frame .r.c.rx.au
1522
1523pack .r.c.rx.net -side top -anchor n -fill both
1524pack .r.c.rx.au -side bottom -expand 1 -fill both
1525
1526checkbutton .r.c.rx.net.on -highlightthickness 0 -text "Listen" -onvalue 0 -offvalue 1 -variable out_mute_var -command {output_mute $out_mute_var} -font $compfont -width 5 -anchor w -padx 4
1527label       .r.c.rx.net.bw -textv bps_in -font $compfont -anchor e
1528pack .r.c.rx.net.on -side left
1529pack .r.c.rx.net.bw -side right -fill x -expand 1
1530
1531frame  .r.c.rx.au.port -bd 0
1532button .r.c.rx.au.port.l0 -highlightthickness 0 -command {incr_port oport oports -1} -font $compfont -bitmap left -relief flat
1533label  .r.c.rx.au.port.l1 -highlightthickness 0 -textv oport -font $compfont -width 10
1534button .r.c.rx.au.port.l2 -highlightthickness 0 -command {incr_port oport oports +1} -font $compfont -bitmap right -relief flat
1535pack   .r.c.rx.au.port -side top -fill x -expand 1
1536pack   .r.c.rx.au.port.l0 -side left -fill y
1537pack   .r.c.rx.au.port.l1 -side left -fill x -expand 1
1538pack   .r.c.rx.au.port.l2 -side left -fill y
1539
1540frame  .r.c.rx.au.pow -relief sunk -bd 2
1541bargraphCreate .r.c.rx.au.pow.bar
1542scale .r.c.rx.au.pow.sli -highlightthickness 0 -from 0 -to 99 -command set_vol -orient horizontal -showvalue false -width 8 -variable volume -resolution 4 -bd 0 -troughcolor black -sliderl 16
1543pack .r.c.rx.au.pow .r.c.rx.au.pow.bar .r.c.rx.au.pow.sli -side top -fill both -expand 1
1544
1545# Device input controls
1546set in_mute_var 1
1547
1548frame .r.c.tx.net
1549frame .r.c.tx.au
1550
1551pack .r.c.tx.net -side top -anchor n  -fill both
1552pack .r.c.tx.au -side bottom -expand 1 -fill both
1553
1554checkbutton .r.c.tx.net.on -highlightthickness 0 -text "Talk" -onvalue 0 -offvalue 1 -variable in_mute_var -command {input_mute $in_mute_var} -font $compfont -width 5 -anchor w -padx 4
1555label       .r.c.tx.net.bw -textv bps_out -font $compfont -anchor e
1556pack .r.c.tx.net.on -side left
1557pack .r.c.tx.net.bw -side right -fill x -expand 1
1558
1559frame  .r.c.tx.au.port -bd 0
1560button .r.c.tx.au.port.l0 -highlightthickness 0 -command {incr_port iport iports -1} -font $compfont -bitmap left -relief flat
1561label  .r.c.tx.au.port.l1 -highlightthickness 0 -textv iport -font $compfont -width 10
1562button .r.c.tx.au.port.l2 -highlightthickness 0 -command {incr_port iport iports +1} -font $compfont -bitmap right -relief flat
1563pack   .r.c.tx.au.port -side top -fill x -expand 1
1564pack   .r.c.tx.au.port.l0 -side left -fill y
1565pack   .r.c.tx.au.port.l1 -side left -fill x -expand 1
1566pack   .r.c.tx.au.port.l2 -side left -fill y
1567
1568frame  .r.c.tx.au.pow -relief sunk -bd 2
1569bargraphCreate .r.c.tx.au.pow.bar
1570scale .r.c.tx.au.pow.sli -highlightthickness 0 -from 0 -to 99 -command set_gain -orient horizontal -showvalue false -width 8 -variable gain -resolution 4 -bd 0 -sliderl 16 -troughco black
1571pack .r.c.tx.au.pow .r.c.tx.au.pow.bar .r.c.tx.au.pow.sli -side top -fill both -expand 1
1572
1573bind all <ButtonPress-3>   {toggle in_mute_var; input_mute $in_mute_var}
1574bind all <ButtonRelease-3> {toggle in_mute_var; input_mute $in_mute_var}
1575bind all <q>               {+if {[winfo class %W] != "Entry"} {do_quit}}
1576
1577# Override default tk behaviour
1578wm protocol . WM_DELETE_WINDOW do_quit
1579
1580if {$win32 == 0} {
1581        wm iconbitmap . rat_small
1582}
1583#wm resizable . 0 1
1584if ([info exists geometry]) {
1585        wm geometry . $geometry
1586}
1587
1588proc averageCharacterWidth {font} {
1589    set sample "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
1590    set slen [string length $sample]
1591    set wpc  [expr [font measure $font $sample] / $slen + 1]
1592    return $wpc
1593}
1594
1595# constrain_window - window, font, characters wide, characters high
1596proc constrain_window {w font cW cH} {
1597   
1598    catch {
1599            set wpc [averageCharacterWidth $font]
1600            set hpc [font metrics $font -ascent]
1601   
1602        # Calculate dimensions
1603            set width [expr $cW * $wpc]
1604            set height [expr $cH * $hpc]
1605            wm geometry $w [format "%sx%s" $width $height]
1606            set dummy ""
1607    } err
1608    if {$err != ""} {
1609        puts "Error: $err"
1610    }
1611}
1612
1613proc tk_optionCmdMenu {w varName firstValue args} {
1614    upvar #0 $varName var
1615 
1616    if ![info exists var] {
1617        set var $firstValue
1618    }
1619    menubutton $w -textvariable $varName -indicatoron 1 -menu $w.menu \
1620            -relief raised -bd 2 -highlightthickness 2 -anchor c
1621
1622    menu $w.menu -tearoff 0
1623    $w.menu add command -label $firstValue -command "set $varName \"$firstValue\""
1624    foreach i $args {
1625        $w.menu add command -label $i -command "set $varName \"$i\""
1626    }
1627    return $w.menu
1628}
1629
1630
1631###############################################################################
1632# Preferences Panel
1633#
1634
1635set prefs_pane "Personal"
1636toplevel .prefs
1637wm title .prefs "Preferences"
1638wm resizable .prefs 0 0
1639wm withdraw  .prefs
1640
1641frame .prefs.m
1642pack .prefs.m -side top -fill x -expand 0 -padx 2 -pady 2
1643frame .prefs.m.f
1644pack .prefs.m.f -padx 0 -pady 0
1645label .prefs.m.f.t -text "Category: "
1646pack .prefs.m.f.t -pady 2 -side left
1647menubutton .prefs.m.f.m -menu .prefs.m.f.m.menu -indicatoron 1 -textvariable prefs_pane -relief raised -width 14
1648pack .prefs.m.f.m -side top
1649menu .prefs.m.f.m.menu -tearoff 0
1650.prefs.m.f.m.menu add command -label "Personal"     -command {set_pane prefs_pane .prefs.pane "Personal"}
1651.prefs.m.f.m.menu add command -label "Transmission" -command {set_pane prefs_pane .prefs.pane "Transmission"; update_codecs_displayed}
1652.prefs.m.f.m.menu add command -label "Reception"    -command {set_pane prefs_pane .prefs.pane "Reception"}
1653.prefs.m.f.m.menu add command -label "Audio"        -command {set_pane prefs_pane .prefs.pane "Audio"}
1654.prefs.m.f.m.menu add command -label "Codecs"        -command {set_pane prefs_pane .prefs.pane "Codecs"; codecs_panel_fill}
1655.prefs.m.f.m.menu add command -label "Security"     -command {set_pane prefs_pane .prefs.pane "Security"}
1656.prefs.m.f.m.menu add command -label "Interface"    -command {set_pane prefs_pane .prefs.pane "Interface"}
1657
1658frame  .prefs.buttons
1659pack   .prefs.buttons       -side bottom -fill x
1660button .prefs.buttons.bye   -text "Cancel" -command {sync_ui_to_engine; wm withdraw .prefs}
1661button .prefs.buttons.apply -text "Apply" -command {wm withdraw .prefs; sync_engine_to_ui}
1662pack   .prefs.buttons.bye .prefs.buttons.apply -side right -padx 2 -pady 2
1663
1664wm protocol .prefs WM_DELETE_WINDOW {sync_ui_to_engine; wm withdraw .prefs}
1665
1666frame .prefs.pane -relief groove -bd 2
1667pack  .prefs.pane -side left -fill both -expand 1 -padx 4 -pady 2
1668
1669# setup width of prefs panel
1670constrain_window .prefs $infofont 56 30
1671
1672# Personal Info Pane ##########################################################
1673set i .prefs.pane.personal
1674frame $i
1675pack $i -fill both -expand 1 -pady 2 -padx 2
1676
1677frame $i.a
1678frame $i.a.f -rel fl
1679pack $i.a -side top -fill both -expand 1
1680pack $i.a.f -side left -fill x -expand 1
1681
1682frame $i.a.f.f -rel fl
1683pack $i.a.f.f
1684
1685label $i.a.f.f.l -width 40 -height 2 -text "The personal details below are conveyed\nto the other conference participants." -justify left -anchor w
1686pack $i.a.f.f.l -side top -anchor w -fill x
1687
1688frame $i.a.f.f.lbls
1689frame $i.a.f.f.ents
1690pack  $i.a.f.f.lbls -side left -fill y
1691pack  $i.a.f.f.ents -side right
1692
1693label $i.a.f.f.lbls.1  -text "Name:"     -anchor w
1694label $i.a.f.f.lbls.2 -text "Email:"    -anchor w
1695label $i.a.f.f.lbls.3 -text "Phone:"    -anchor w
1696label $i.a.f.f.lbls.4   -text "Location:" -anchor w
1697label $i.a.f.f.lbls.5  -text "Note:" -anchor w
1698pack $i.a.f.f.lbls.1 $i.a.f.f.lbls.2 $i.a.f.f.lbls.3 $i.a.f.f.lbls.4 $i.a.f.f.lbls.5 -fill x -anchor w -side top
1699
1700entry $i.a.f.f.ents.name -width 28 -highlightthickness 0 -textvariable rtcp_name
1701entry $i.a.f.f.ents.email -width 28 -highlightthickness 0 -textvariable rtcp_email
1702entry $i.a.f.f.ents.phone -width 28 -highlightthickness 0 -textvariable rtcp_phone
1703entry $i.a.f.f.ents.loc  -width 28 -highlightthickness 0 -textvariable rtcp_loc
1704entry $i.a.f.f.ents.note  -width 28 -highlightthickness 0 -textvariable rtcp_note
1705pack $i.a.f.f.ents.name $i.a.f.f.ents.email $i.a.f.f.ents.phone $i.a.f.f.ents.loc $i.a.f.f.ents.note -anchor n -expand 0
1706
1707proc update_user_panel {} {
1708    global my_ssrc NAME EMAIL PHONE LOC NOTE
1709    global rtcp_name rtcp_email rtcp_phone rtcp_loc rtcp_note
1710    if {[info exists my_ssrc]} {
1711        set rtcp_name  $NAME($my_ssrc)
1712        set rtcp_email $EMAIL($my_ssrc)
1713        set rtcp_phone $PHONE($my_ssrc)
1714        set rtcp_loc   $LOC($my_ssrc)
1715        set rtcp_note  $NOTE($my_ssrc)
1716    }
1717}
1718
1719# Transmission Pane ###########################################################
1720set i .prefs.pane.transmission
1721frame $i
1722frame $i.dd
1723frame $i.cc
1724frame $i.cc.van
1725frame $i.cc.red
1726frame $i.cc.layer
1727frame $i.cc.int
1728label $i.intro -text "This panel allows you to select codecs for transmission.  The choice\nof codecs available depends on the sampling rate and channels\nin the audio panel."
1729frame $i.title1-f -relief raised
1730label $i.title1-f.l -text "Audio Encoding"
1731pack $i.intro $i.title1-f $i.title1-f.l $i.dd -side top -fill x
1732
1733#pack $i.dd -fill x -side top -anchor n
1734
1735frame $i.title2-f -relief raised
1736label $i.title2-f.l -text "Channel Coding Options"
1737pack $i.title2-f $i.title2-f.l -fill x -side top
1738pack $i.cc -fill x -anchor w -pady 1
1739
1740pack $i.cc.van $i.cc.red $i.cc.layer -fill x -anchor w -pady 0
1741# interleaving panel $i.cc.int not packed since interleaving isn't support in this release
1742frame $i.dd.units
1743frame $i.dd.pri
1744
1745pack $i.dd.units $i.dd.pri -side right -fill x
1746
1747label $i.dd.pri.l -text "Encoding:"
1748menubutton $i.dd.pri.m -menu $i.dd.pri.m.menu -indicatoron 1 -textvariable prenc -relief raised -width 13
1749pack $i.dd.pri.l $i.dd.pri.m -side top
1750# fill in codecs
1751menu $i.dd.pri.m.menu -tearoff 0
1752
1753label $i.dd.units.l -text "Units:"
1754tk_optionCmdMenu $i.dd.units.m upp 1 2 4 8
1755$i.dd.units.m configure -width 13 -highlightthickness 0 -bd 1
1756pack $i.dd.units.l $i.dd.units.m -side top -fill x
1757
1758radiobutton $i.cc.van.rb -text "No Loss Protection" -justify right -value none        -variable channel_var
1759radiobutton $i.cc.red.rb -text "Redundancy"         -justify right -value redundancy  -variable channel_var
1760radiobutton $i.cc.layer.rb -text "Layering"                     -justify right -value layering    -variable channel_var
1761radiobutton $i.cc.int.rb -text "Interleaving"       -justify right -value interleaved -variable channel_var -state disabled
1762pack $i.cc.van.rb $i.cc.red.rb $i.cc.layer.rb $i.cc.int.rb -side left -anchor nw -padx 2
1763
1764frame $i.cc.red.fc
1765label $i.cc.red.fc.l -text "Encoding:"
1766menubutton $i.cc.red.fc.m -textvariable secenc -indicatoron 1 -menu $i.cc.red.fc.m.menu -relief raised -width 13
1767menu $i.cc.red.fc.m.menu -tearoff 0
1768
1769frame $i.cc.red.u
1770label $i.cc.red.u.l -text "Offset in Pkts:"
1771tk_optionCmdMenu $i.cc.red.u.m red_off "1" "2" "4" "8" 
1772$i.cc.red.u.m configure -width 13 -highlightthickness 0 -bd 1
1773pack $i.cc.red.u -side right -anchor e -fill y
1774pack $i.cc.red.u.l $i.cc.red.u.m -fill x
1775pack $i.cc.red.fc -side right
1776pack $i.cc.red.fc.l $i.cc.red.fc.m
1777
1778frame $i.cc.layer.fc
1779label $i.cc.layer.fc.l -text "Layers:"
1780menubutton $i.cc.layer.fc.m -textvariable layerenc -indicatoron 1 -menu $i.cc.layer.fc.m.menu -relief raised -width 13
1781menu $i.cc.layer.fc.m.menu -tearoff 0
1782pack $i.cc.layer.fc -side right
1783pack $i.cc.layer.fc.l $i.cc.layer.fc.m
1784
1785frame $i.cc.int.zz
1786label $i.cc.int.zz.l -text "Units:"
1787tk_optionCmdMenu $i.cc.int.zz.m int_units 2 4 6 8
1788$i.cc.int.zz.m configure -width 13 -highlightthickness 0 -bd 1 -state disabled
1789
1790frame $i.cc.int.fc
1791label $i.cc.int.fc.l -text "Separation:" 
1792tk_optionCmdMenu $i.cc.int.fc.m int_gap 2 4 6 8
1793$i.cc.int.fc.m configure -width 13 -highlightthickness 0 -bd 1 -state disabled
1794
1795pack $i.cc.int.fc $i.cc.int.zz -side right
1796pack $i.cc.int.fc.l $i.cc.int.fc.m -fill x -expand 1
1797pack $i.cc.int.zz.l $i.cc.int.zz.m -fill x -expand 1
1798
1799# Reception Pane ##############################################################
1800set i .prefs.pane.reception
1801frame $i 
1802frame $i.r -rel f
1803frame $i.o -rel f
1804frame $i.c -rel f
1805pack $i.r -side top -fill x -pady 0 -ipady 1
1806pack $i.o -side top -fill both  -pady 1
1807pack $i.c -side top -fill both  -pady 1 -expand 1
1808label $i.r.l -text "Repair Scheme:"
1809tk_optionCmdMenu $i.r.m repair_var {}
1810
1811label $i.r.ls -text "Sample Rate Conversion"
1812tk_optionCmdMenu $i.r.ms convert_var {}
1813
1814$i.r.m  configure -width 20 -bd 1
1815$i.r.ms configure -width 20 -bd 1
1816pack $i.r.l $i.r.m $i.r.ls $i.r.ms -side top
1817
1818frame $i.o.f
1819checkbutton $i.o.f.cb -text "Limit Playout Delay" -variable limit_var
1820frame $i.o.f.fl
1821label $i.o.f.fl.l1 -text "Minimum Delay (ms)" 
1822scale $i.o.f.fl.scmin -orient horizontal -from 0 -to 1000    -variable min_var -font $smallfont
1823frame $i.o.f.fr
1824label $i.o.f.fr.l2 -text "Maximum Delay (ms)"           
1825scale $i.o.f.fr.scmax -orient horizontal -from 1000 -to 2000 -variable max_var -font $smallfont
1826pack $i.o.f
1827pack $i.o.f.cb -side top -fill x
1828pack $i.o.f.fl $i.o.f.fr -side left
1829pack $i.o.f.fl.l1 $i.o.f.fl.scmin $i.o.f.fr.l2 $i.o.f.fr.scmax -side top -fill x -expand 1
1830
1831frame $i.c.f
1832frame $i.c.f.f
1833checkbutton $i.c.f.f.lec -text "Lecture Mode"       -variable lecture_var
1834checkbutton $i.c.f.f.ext -text "3D Audio Rendering" -variable 3d_audio_var
1835
1836pack $i.c.f -fill x -side left -expand 1
1837pack $i.c.f.f
1838pack $i.c.f.f.lec -side top  -anchor w
1839pack $i.c.f.f.ext -side top  -anchor w
1840
1841# Audio #######################################################################
1842set i .prefs.pane.audio
1843frame $i 
1844frame $i.dd -rel fl
1845pack $i.dd -fill both -expand 1 -anchor w -pady 1
1846
1847label $i.dd.title -height 2 -width 40 -text "This panel allows for the selection of alternate audio devices\nand the configuring of device related options." -justify left
1848pack $i.dd.title -fill x
1849
1850frame $i.dd.device
1851pack $i.dd.device -side top
1852
1853label $i.dd.device.l -text "Audio Device:"
1854pack  $i.dd.device.l -side top -fill x
1855menubutton $i.dd.device.mdev -menu $i.dd.device.mdev.menu -indicatoron 1 \
1856                                -textvariable audio_device -relief raised -width 5
1857pack $i.dd.device.mdev -fill x -expand 1
1858menu $i.dd.device.mdev.menu -tearoff 0
1859
1860frame $i.dd.sampling 
1861pack  $i.dd.sampling
1862
1863frame $i.dd.sampling.freq
1864frame $i.dd.sampling.ch_in
1865pack $i.dd.sampling.freq $i.dd.sampling.ch_in -side left -fill x
1866
1867label $i.dd.sampling.freq.l   -text "Sample Rate:   "
1868label $i.dd.sampling.ch_in.l  -text "Channels:"
1869pack $i.dd.sampling.freq.l $i.dd.sampling.ch_in.l -fill x
1870
1871menubutton $i.dd.sampling.freq.mb -menu $i.dd.sampling.freq.mb.m -indicatoron 1 \
1872                                  -textvariable freq -relief raised
1873pack $i.dd.sampling.freq.mb -side left -fill x -expand 1
1874menu $i.dd.sampling.freq.mb.m
1875
1876menubutton $i.dd.sampling.ch_in.mb -menu $i.dd.sampling.ch_in.mb.m -indicatoron 1 \
1877                                  -textvariable ichannels -relief raised
1878pack $i.dd.sampling.ch_in.mb -side left -fill x -expand 1
1879menu $i.dd.sampling.ch_in.mb.m
1880
1881frame $i.dd.cks
1882pack $i.dd.cks -fill both -expand 1
1883frame $i.dd.cks.f
1884frame $i.dd.cks.f.f
1885checkbutton $i.dd.cks.f.f.silence  -text "Silence Suppression"    -variable silence_var
1886checkbutton $i.dd.cks.f.f.agc      -text "Automatic Gain Control" -variable agc_var
1887checkbutton $i.dd.cks.f.f.loop     -text "Audio Loopback"         -variable audio_loop_var
1888checkbutton $i.dd.cks.f.f.suppress -text "Echo Suppression"       -variable echo_var
1889pack $i.dd.cks.f -fill x -side top -expand 1
1890pack $i.dd.cks.f.f
1891pack $i.dd.cks.f.f.silence $i.dd.cks.f.f.agc $i.dd.cks.f.f.loop $i.dd.cks.f.f.suppress -side top -anchor w
1892
1893# Codecs pane #################################################################
1894set i .prefs.pane.codecs
1895frame $i 
1896
1897
1898frame $i.of -rel fl
1899pack  $i.of -fill both -expand 1 -anchor w -pady 1 -side top
1900
1901message $i.of.l -width 30c -justify left -text "This panel shows available codecs and allows RTP payload re-mapping." 
1902pack $i.of.l -side top -fill x
1903
1904frame   $i.of.codecs
1905
1906pack    $i.of.codecs -side left -padx 2 -fill y
1907frame   $i.of.codecs.l -rel raised
1908label   $i.of.codecs.l.l -text "Codec"
1909listbox $i.of.codecs.lb -width 20 -yscrollcommand "$i.of.codecs.scroll set" -relief fl -bg white
1910scrollbar $i.of.codecs.scroll -command "$i.of.codecs.lb yview" -rel fl
1911pack    $i.of.codecs.l $i.of.codecs.l.l -side top -fill x
1912pack    $i.of.codecs.scroll $i.of.codecs.lb -side left -fill both
1913
1914frame   $i.of.details -bd 0
1915pack    $i.of.details -side left -fill both -expand 1 -anchor n
1916
1917frame $i.of.details.upper
1918pack $i.of.details.upper -fill x
1919
1920frame $i.of.details.desc
1921pack $i.of.details.desc -side top -fill x
1922
1923frame $i.of.details.pt
1924pack $i.of.details.pt -side bottom -fill x -anchor s
1925label $i.of.details.pt.l -anchor w -text "RTP payload:"
1926pack  $i.of.details.pt.l -side left -anchor w
1927
1928entry $i.of.details.pt.e -width 4
1929pack  $i.of.details.pt.e -side left -padx 4
1930
1931button $i.of.details.pt.b -text "Map Codec" -command map_codec
1932pack  $i.of.details.pt.b -side right -padx 4
1933
1934frame $i.of.details.upper.l0 -relief raised
1935label $i.of.details.upper.l0.l -text "Details"
1936pack $i.of.details.upper.l0 $i.of.details.upper.l0.l -side top -fill x -expand 1
1937
1938frame $i.of.details.upper.l
1939pack $i.of.details.upper.l -side left
1940label $i.of.details.upper.l.0 -text "Short name:"  -anchor w
1941label $i.of.details.upper.l.1 -text "Sample Rate (Hz):" -anchor w
1942label $i.of.details.upper.l.2 -text "Channels:"    -anchor w
1943label $i.of.details.upper.l.3 -text "Bitrate (kbps):"     -anchor w
1944label $i.of.details.upper.l.4 -text "RTP Payload:" -anchor w
1945label $i.of.details.upper.l.5 -text "Capability:" -anchor w
1946label $i.of.details.upper.l.6 -text "Layers:" -anchor w
1947
1948for {set idx 0} {$idx < 7} {incr idx} {
1949    pack $i.of.details.upper.l.$idx -side top -fill x
1950}
1951
1952frame $i.of.details.upper.r
1953pack $i.of.details.upper.r -side left -fill x -expand 1
1954label $i.of.details.upper.r.0 -anchor w
1955label $i.of.details.upper.r.1 -anchor w
1956label $i.of.details.upper.r.2 -anchor w
1957label $i.of.details.upper.r.3 -anchor w
1958label $i.of.details.upper.r.4 -anchor w
1959label $i.of.details.upper.r.5 -anchor w
1960label $i.of.details.upper.r.6 -anchor w
1961
1962for {set idx 0} {$idx < 7} {incr idx} {
1963    pack $i.of.details.upper.r.$idx -side top -fill x
1964}
1965
1966set descw [expr [averageCharacterWidth $infofont] * 30]
1967label $i.of.details.desc.l -text "Description:" -anchor w -wraplength $descw -justify left
1968pack $i.of.details.desc.l -side left -fill x
1969unset descw
1970
1971bind $i.of.codecs.lb <1> {
1972    codecs_panel_select [%W index @%x,%y]
1973}
1974
1975bind $i.of.codecs.lb <ButtonRelease-1> {
1976    codecs_panel_select [%W index @%x,%y]
1977}
1978proc codecs_panel_fill {} {
1979    global codecs
1980
1981    .prefs.pane.codecs.of.codecs.lb delete 0 end
1982
1983    foreach {c} $codecs {
1984        .prefs.pane.codecs.of.codecs.lb insert end $c
1985    }
1986}
1987
1988set last_selected_codec -1
1989
1990proc codecs_panel_select { idx } {
1991    global codecs codec_nick_name codec_rate codec_channels codec_pt codec_block_size codec_data_size codec_desc codec_caps codec_layers
1992    global last_selected_codec
1993
1994    set last_selected_codec $idx
1995
1996    set codec [lindex $codecs $idx]
1997    set root  .prefs.pane.codecs.of.details.upper.r
1998    $root.0 configure -text $codec_nick_name($codec)
1999    $root.1 configure -text $codec_rate($codec)
2000    $root.2 configure -text $codec_channels($codec)
2001
2002    set fps [expr $codec_rate($codec) * 2 * $codec_channels($codec) / $codec_block_size($codec) ]
2003    set kbps [expr 8 * $fps * $codec_data_size($codec) / 1000.0]
2004    $root.3 configure -text [format "%.1f" $kbps]
2005
2006    $root.4 configure -text $codec_pt($codec)
2007    $root.5 configure -text $codec_caps($codec)
2008    $root.6 configure -text $codec_layers($codec)
2009   
2010    .prefs.pane.codecs.of.details.desc.l configure -text "Description: $codec_desc($codec)"
2011
2012}
2013
2014proc map_codec {} {
2015    global codecs last_selected_codec
2016
2017    set idx $last_selected_codec
2018
2019    if {$last_selected_codec == -1} {
2020        return
2021    }
2022
2023    set pt [.prefs.pane.codecs.of.details.pt.e get]
2024    .prefs.pane.codecs.of.details.pt.e delete 0 end
2025
2026    set ptnot [string trim $pt 1234567890]
2027    if {$ptnot != ""} {
2028        return
2029    }
2030
2031    set codec [lindex $codecs $idx]
2032
2033    mbus_send "R" "tool.rat.payload.set" "[mbus_encode_str $codec] $pt"
2034    after 1000 codecs_panel_select $idx
2035}
2036
2037# Security Pane ###############################################################
2038set i .prefs.pane.security
2039frame $i 
2040frame $i.a -rel fl
2041frame $i.a.f
2042frame $i.a.f.f
2043label $i.a.f.f.l -anchor w -justify left -text "Your communication can be secured with\nDES encryption.  Only conference participants\nwith the same key can receive audio data when\nencryption is enabled."
2044pack $i.a.f.f.l
2045pack $i.a -side top -fill both -expand 1
2046label $i.a.f.f.lbl -text "Key:"
2047entry $i.a.f.f.e -width 28 -textvariable key
2048checkbutton $i.a.f.f.cb -text "Enabled" -variable key_var
2049pack $i.a.f -fill x -side left -expand 1
2050pack $i.a.f.f
2051pack $i.a.f.f.lbl $i.a.f.f.e $i.a.f.f.cb -side left -pady 4 -padx 2 -fill x
2052
2053# Interface Pane ##############################################################
2054set i .prefs.pane.interface
2055frame $i 
2056frame $i.a -rel fl
2057frame $i.a.f
2058frame $i.a.f.f
2059label $i.a.f.f.l -anchor w -justify left -text "The following features may be\ndisabled to conserve processing\npower."
2060pack $i.a -side top -fill both -expand 1
2061pack $i.a.f -fill x -side left -expand 1
2062checkbutton $i.a.f.f.power   -text "Powermeters active"       -variable meter_var
2063checkbutton $i.a.f.f.balloon -text "Balloon help"             -variable help_on
2064checkbutton $i.a.f.f.matrix  -text "Reception quality matrix" -variable matrix_on -command chart_show
2065checkbutton $i.a.f.f.plist   -text "Participant list"         -variable plist_on  -command toggle_plist
2066checkbutton $i.a.f.f.fwin    -text "File Control Window"      -variable files_on  -command file_show
2067pack $i.a.f.f $i.a.f.f.l
2068pack $i.a.f.f.power $i.a.f.f.balloon $i.a.f.f.matrix $i.a.f.f.plist $i.a.f.f.fwin -side top -anchor w
2069
2070proc set_pane {p base desc} {
2071    upvar 1 $p pane
2072    set tpane [string tolower [lindex [split $pane] 0]]
2073    pack forget $base.$tpane
2074    set tpane [string tolower [lindex [split $desc] 0]]
2075    pack $base.$tpane -fill both -expand 1 -padx 2 -pady 2
2076    set pane $desc
2077}
2078
2079# Initialise "About..." toplevel window
2080toplevel   .about
2081frame      .about.rim -relief groove -bd 2
2082frame      .about.m
2083frame      .about.rim.d
2084pack .about.m -fill x
2085pack .about.rim -padx 4 -pady 2 -side top -fill both -expand 1
2086pack .about.rim.d -side top -fill both -expand 1
2087
2088frame .about.m.f
2089label .about.m.f.l -text "Category:"
2090menubutton .about.m.f.mb -menu .about.m.f.mb.menu -indicatoron 1 -textvariable about_pane -relief raised -width 10
2091menu .about.m.f.mb.menu -tearoff 0
2092.about.m.f.mb.menu add command -label "Credits"   -command {set_pane about_pane .about.rim.d "Credits"   }
2093.about.m.f.mb.menu add command -label "Feedback"  -command {set_pane about_pane .about.rim.d "Feedback"  }
2094.about.m.f.mb.menu add command -label "Copyright" -command {set_pane about_pane .about.rim.d "Copyright" }
2095
2096pack .about.m.f
2097pack .about.m.f.l .about.m.f.mb -side left
2098
2099frame     .about.rim.d.copyright
2100frame     .about.rim.d.copyright.f -relief flat
2101frame     .about.rim.d.copyright.f.f
2102text      .about.rim.d.copyright.f.f.blurb -height 14 -yscrollcommand ".about.rim.d.copyright.f.f.scroll set" -relief flat -bg white
2103scrollbar .about.rim.d.copyright.f.f.scroll -command ".about.rim.d.copyright.f.f.blurb yview" -relief flat
2104
2105pack      .about.rim.d.copyright.f -expand 1 -fill both
2106pack      .about.rim.d.copyright.f.f -expand 1 -fill both
2107pack      .about.rim.d.copyright.f.f.scroll -side left -fill y -expand 1
2108pack      .about.rim.d.copyright.f.f.blurb -side left -fill y -expand 1
2109
2110frame     .about.rim.d.credits
2111frame     .about.rim.d.credits.f -relief flat
2112frame     .about.rim.d.credits.f.f
2113pack      .about.rim.d.credits.f -fill both -expand 1
2114pack      .about.rim.d.credits.f.f -side left -fill x -expand 1
2115label     .about.rim.d.credits.f.f.1                  -text "The Robust-Audio Tool was developed in the Department of\nComputer Science, University College London.\n\nProject Supervision:"
2116label     .about.rim.d.credits.f.f.2 -foreground blue -text Good
2117label     .about.rim.d.credits.f.f.3                  -text "Development Team:"
2118label     .about.rim.d.credits.f.f.4 -foreground blue -text Bad
2119label     .about.rim.d.credits.f.f.5                  -text "Additional Contributions:"
2120label     .about.rim.d.credits.f.f.6 -foreground blue -text Ugly
2121for {set i 1} {$i<=6} {incr i} {
2122    pack  .about.rim.d.credits.f.f.$i -side top -fill x -anchor n
2123}
2124
2125button    .about.dismiss -text Dismiss -command "wm withdraw .about"
2126pack      .about.dismiss -side bottom -anchor e -padx 2 -pady 2
2127
2128frame     .about.rim.d.feedback
2129frame     .about.rim.d.feedback.f -relief flat
2130frame     .about.rim.d.feedback.f.f
2131pack      .about.rim.d.feedback.f -fill both -expand 1
2132pack      .about.rim.d.feedback.f.f -side left -fill x -expand 1
2133label     .about.rim.d.feedback.f.f.1                  -text "Comments, suggestions, and bug-reports should be sent to:"
2134label     .about.rim.d.feedback.f.f.2 -foreground blue -text "rat-trap@cs.ucl.ac.uk\n"
2135label     .about.rim.d.feedback.f.f.3                  -text "Further information is available on the world-wide web at:"
2136label     .about.rim.d.feedback.f.f.4 -foreground blue -text "http://www-mice.cs.ucl.ac.uk/multimedia/software/rat/\n"
2137for {set i 1} {$i<=4} {incr i} {
2138    pack  .about.rim.d.feedback.f.f.$i -side top -fill x
2139}
2140
2141wm withdraw  .about
2142wm title     .about "About RAT"
2143wm resizable .about 0 0
2144set about_pane Copyright
2145set_pane about_pane .about.rim.d "Credits" 
2146constrain_window .about $infofont 64 25
2147
2148.about.rim.d.copyright.f.f.blurb insert end \
2149{Copyright (C) 1995-2000 University College London
2150All rights reserved.
2151
2152Redistribution and use in source and binary forms, with or without
2153modification, is permitted, provided that the following conditions
2154are met:
2155
21561. Redistributions of source code must retain the above
2157   copyright notice, this list of conditions and the
2158   following disclaimer.
2159
21602. Redistributions in binary form must reproduce the above
2161   copyright notice, this list of conditions and the
2162   following disclaimer in the documentation and/or other
2163   materials provided with the distribution.
2164
21653. All advertising materials mentioning features or use of
2166   this software must display the following acknowledgement:
2167
2168     "This product includes software developed by the
2169     Computer Science Department at University College
2170     London."
2171
21724. Neither the name of the University nor of the Department
2173   may be used to endorse or promote products derived from
2174   this software without specific prior written permission.
2175
2176THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
2177"AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
2178BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
2179AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
2180SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2181INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2182DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2183SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2184OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2185LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2186(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
2187THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2188OF SUCH DAMAGE.
2189
2190This software is derived, in part, from publically available
2191source code with the following copyright:
2192
2193Copyright (C) 1991-1993 Regents of the University of California
2194Copyright (C) 1992 Stichting Mathematisch Centrum, Amsterdam
2195Copyright (C) 1991-1992 RSA Data Security, Inc
2196Copyright (C) 1992 Jutta Degener and Carsten Bormann, TU Berlin
2197Copyright (C) 1994 Paul Stewart
2198Copyright (C) 1996 Regents of the University of California
2199
2200This product includes software developed by the Computer
2201Systems Engineering Group and by the Network Research Group
2202at Lawrence Berkeley Laboratory.
2203
2204The WB-ADPCM algorithm was developed by British Telecommunications
2205plc.  Permission has been granted to use it for non-commercial
2206research and development projects.  BT retain the intellectual
2207property rights to this algorithm.
2208
2209Encryption features of this software use the RSA Data
2210Security, Inc. MD5 Message-Digest Algorithm.
2211}
2212
2213proc shuffle_rats {args} {
2214    # This should really animate the movement and play fruit-machine sounds.... :-)
2215    set r ""
2216    set end [llength $args]
2217    set l 0
2218    while { $l < $end } {
2219        set toget [expr abs([clock clicks]) % [llength $args]]
2220        set r [format "%s%s  " $r [lindex $args $toget]]
2221        set args [lreplace $args $toget $toget]
2222        lappend used $toget
2223        if {$l >0 && [expr ($l + 1) % 3] == 0} {
2224            set r "$r\n"
2225        }
2226        incr l
2227    }
2228    return $r
2229}
2230
2231proc jiggle_credits {} {
2232# Software really developed by the Socialist Department of Computer Science
2233    .about.rim.d.credits.f.f.2 configure -text [shuffle_rats "Angela Sasse" "Vicky Hardman"]
2234    .about.rim.d.credits.f.f.4 configure -text [shuffle_rats "Colin Perkins" "Orion Hodson"]
2235    .about.rim.d.credits.f.f.6 configure -text [shuffle_rats "Isidor Kouvelas" "Darren Harris" "Anna Watson" "Mark Handley" "Jon Crowcroft" "Marcus Iken" "Kris Hasler" "Tristan Henderson" "Dimitrios Miras" "Socrates Varakliotis"]
2236}
2237
2238proc sync_ui_to_engine {} {
2239    # the next time the display is shown, it needs to reflect the
2240    # state of the audio engine.
2241    mbus_send "R" "tool.rat.settings" ""
2242}
2243
2244proc sync_engine_to_ui {} {
2245    # make audio engine concur with ui
2246    global my_ssrc rtcp_name rtcp_email rtcp_phone rtcp_loc rtcp_note
2247    global prenc upp channel_var secenc layerenc red_off int_gap int_units
2248    global silence_var agc_var audio_loop_var echo_var
2249    global repair_var limit_var min_var max_var lecture_var 3d_audio_var convert_var 
2250    global meter_var gain volume iport oport
2251    global in_mute_var out_mute_var ichannels freq key key_var
2252    global audio_device received
2253
2254    #rtcp details
2255    mbus_send "R" "rtp.source.name"  "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_name]"
2256    mbus_send "R" "rtp.source.email" "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_email]"
2257    mbus_send "R" "rtp.source.phone" "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_phone]"
2258    mbus_send "R" "rtp.source.loc"   "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_loc]"
2259    mbus_send "R" "rtp.source.note"   "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_note]"
2260
2261    #cheat to update my details right away (it's disgusting)
2262    mbus_recv_rtp.source.name  $my_ssrc "$rtcp_name"
2263    mbus_recv_rtp.source.email $my_ssrc "$rtcp_email"
2264    mbus_recv_rtp.source.phone $my_ssrc "$rtcp_phone"
2265    mbus_recv_rtp.source.loc   $my_ssrc "$rtcp_loc"
2266    mbus_recv_rtp.source.note  $my_ssrc "$rtcp_note"
2267   
2268    #transmission details
2269    mbus_send "R" "tool.rat.codec"      "[mbus_encode_str $prenc] [mbus_encode_str $ichannels] [mbus_encode_str $freq]"
2270    mbus_send "R" "tool.rat.rate"         $upp
2271
2272    switch $channel_var {
2273        none         {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var]"}
2274        redundancy   {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var] [mbus_encode_str $secenc] $red_off"}
2275        interleaved {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var] $int_gap $int_units"}
2276        layering        {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var] [mbus_encode_str $prenc] [mbus_encode_str $ichannels] [mbus_encode_str $freq] $layerenc"}
2277        *           {error "unknown channel coding scheme $channel_var"}
2278    }
2279
2280    mbus_send "R" "tool.rat.silence"       $silence_var
2281    mbus_send "R" "tool.rat.agc"           $agc_var
2282    mbus_send "R" "tool.rat.loopback"      $audio_loop_var
2283    mbus_send "R" "tool.rat.echo.suppress" $echo_var
2284
2285    #Reception Options
2286    mbus_send "R" "audio.channel.repair"   [mbus_encode_str $repair_var]
2287    mbus_send "R" "tool.rat.playout.limit" $limit_var
2288    mbus_send "R" "tool.rat.playout.min"   $min_var
2289    mbus_send "R" "tool.rat.playout.max"   $max_var
2290    mbus_send "R" "tool.rat.lecture"       $lecture_var
2291    mbus_send "R" "tool.rat.3d.enabled"    $3d_audio_var
2292    mbus_send "R" "tool.rat.converter"     [mbus_encode_str $convert_var]
2293
2294    #Security
2295    if {$key_var==1 && [string length $key]!=0} {
2296        mbus_send "R" "security.encryption.key" [mbus_encode_str $key]
2297    } else {
2298        mbus_send "R" "security.encryption.key" [mbus_encode_str ""]
2299    }
2300
2301    #Interface
2302    mbus_send "R" "tool.rat.powermeter"   $meter_var
2303
2304    #device
2305    mbus_send "R" "audio.device"        [mbus_encode_str "$audio_device"]
2306    if {$received(gain)} {
2307        mbus_send "R" "audio.input.gain"    $gain
2308    }
2309    if {$received(volume)} {
2310        mbus_send "R" "audio.output.gain"   $volume
2311    }
2312    mbus_send "R" "audio.input.port"    [mbus_encode_str $iport]
2313    mbus_send "R" "audio.output.port"   [mbus_encode_str $oport]
2314    mbus_send "R" "audio.input.mute"    $in_mute_var
2315    mbus_send "R" "audio.output.mute"   $out_mute_var
2316}
2317
2318#
2319# Routines to display the "chart" of RTCP RR statistics...
2320#
2321
2322toplevel  .chart
2323canvas    .chart.c  -xscrollcommand {.chart.sb set} -yscrollcommand {.chart.sr set}
2324frame     .chart.c.f
2325scrollbar .chart.sr -orient vertical   -command {.chart.c yview}
2326scrollbar .chart.sb -orient horizontal -command {.chart.c xview}
2327
2328pack .chart.sb -side bottom -fill x    -expand 0 -anchor s
2329pack .chart.sr -side right  -fill y    -expand 0 -anchor e
2330pack .chart.c  -side left   -fill both -expand 1 -anchor n
2331
2332.chart.c create window 0 0 -anchor nw -window .chart.c.f
2333
2334proc mtrace_callback {fd src dst} {
2335        if [winfo exists .mtrace-$src-$dst] {
2336                .mtrace-$src-$dst.t insert end [read $fd]
2337        } else {
2338                # The user has closed the mtrace window before the trace has completed
2339                close $fd
2340        }
2341        if [eof $fd] {
2342                close $fd
2343        }
2344}
2345
2346proc mtrace {src dst} {
2347        global CNAME group_addr
2348        regsub {.*@([0-9]+.[0-9]+.[0-9]+.[0-9]+)} $CNAME($src) {\1} src_addr
2349        regsub {.*@([0-9]+.[0-9]+.[0-9]+.[0-9]+)} $CNAME($dst) {\1} dst_addr
2350
2351        toplevel  .mtrace-$src-$dst
2352        text      .mtrace-$src-$dst.t -background white -font "Courier 8" -wrap none \
2353                                      -yscrollcommand ".mtrace-$src-$dst.sr set" \
2354                                      -xscrollcommand ".mtrace-$src-$dst.sb set"
2355        scrollbar .mtrace-$src-$dst.sb -command ".mtrace-$src-$dst.t xview" -orient horizontal
2356        scrollbar .mtrace-$src-$dst.sr -command ".mtrace-$src-$dst.t yview" -orient vertical
2357        pack .mtrace-$src-$dst.sb -fill x    -expand 0 -side bottom -anchor s
2358        pack .mtrace-$src-$dst.sr -fill y    -expand 0 -side right  -anchor e
2359        pack .mtrace-$src-$dst.t  -fill both -expand 1 -side left   -anchor w
2360
2361        wm title .mtrace-$src-$dst "mtrace from $src_addr to $dst_addr via group $group_addr"
2362
2363        set fd [open "|mtrace $src_addr $dst_addr $group_addr" "r"]
2364        fconfigure $fd -blocking 0
2365        fileevent  $fd readable "mtrace_callback $fd $src $dst"
2366}
2367
2368toplevel .chart_popup       -bg black
2369label    .chart_popup.text  -bg lavender -justify left
2370pack .chart_popup.text -side top -anchor w -fill x
2371wm transient        .chart_popup .
2372wm withdraw         .chart_popup
2373wm overrideredirect .chart_popup true
2374
2375proc chart_popup_show {window} {
2376        global chart_popup_src chart_popup_dst chart_popup_id NAME
2377        .chart_popup.text  configure -text "From: $NAME($chart_popup_src($window))\nTo: $NAME($chart_popup_dst($window))"
2378        # Beware! Don't put the popup under the cursor! Else we get window enter
2379        # for .help and leave for $window, making us hide_help which removes the
2380        # help window, giving us a window enter for $window making us popup the
2381        # help again.....
2382        if {[winfo width $window] > [winfo height $window]} {
2383            set xpos [expr [winfo pointerx $window] + 10]
2384            set ypos [expr [winfo rooty    $window] + [winfo height $window] + 4]
2385        } else {
2386            set xpos [expr [winfo rootx    $window] + [winfo width $window] + 4]
2387            set ypos [expr [winfo pointery $window] + 10]
2388        }
2389       
2390        wm geometry  .chart_popup +$xpos+$ypos
2391        set chart_popup_id [after 100 wm deiconify .chart_popup]
2392        raise .chart_popup $window
2393}
2394
2395proc chart_popup_hide {window} {
2396        global chart_popup_id
2397        if {[info exists chart_popup_id]} {
2398                after cancel $chart_popup_id
2399        }
2400        wm withdraw .chart_popup
2401}
2402
2403proc chart_popup_add {window src dst} {
2404        global chart_popup_src chart_popup_dst
2405        set chart_popup_src($window) $src
2406        set chart_popup_dst($window) $dst
2407        bind $window <Enter>    "+chart_popup_show $window"
2408        bind $window <Leave>    "+chart_popup_hide $window"
2409}
2410
2411proc chart_add {ssrc} {
2412        global NAME
2413        frame  .chart.c.f.$ssrc
2414        frame  .chart.c.f.$ssrc.f
2415        button .chart.c.f.$ssrc.l -width 25 -text $ssrc -padx 0 -pady 0 -anchor w -relief flat -command "toggle_stats $ssrc"
2416        pack   .chart.c.f.$ssrc.f -expand 0 -anchor e -side right
2417        pack   .chart.c.f.$ssrc.l -expand 1 -anchor w -fill x -side left
2418        pack   .chart.c.f.$ssrc   -expand 1 -anchor n -fill x -side top
2419        foreach s [pack slaves .chart.c.f] {
2420                regsub {.chart.c.f.(.*)} $s {\1} s
2421                button .chart.c.f.$s.f.$ssrc -width 4 -text "" -background white -padx 0 -pady 0 -command "mtrace $s $ssrc"
2422                pack   .chart.c.f.$s.f.$ssrc -expand 0 -side left
2423                chart_popup_add .chart.c.f.$s.f.$ssrc $s $ssrc
2424                if {![winfo exists .chart.c.f.$ssrc.f.$s]} {
2425                        button .chart.c.f.$ssrc.f.$s -width 4 -text "" -background white -padx 0 -pady 0 -command "mtrace $ssrc $s"
2426                        pack   .chart.c.f.$ssrc.f.$s -expand 0 -side left
2427                        chart_popup_add .chart.c.f.$ssrc.f.$s $ssrc $s
2428                }
2429        }
2430        update
2431        .chart.c configure -scrollregion "0.0 0.0 [winfo width .chart.c.f] [winfo height .chart.c.f]"
2432}
2433
2434proc chart_remove {ssrc} {
2435        destroy .chart.c.f.$ssrc
2436        foreach s [pack slaves .chart.c.f] {
2437                regsub {.chart.c.f.(.*)} $s {\1} s
2438                destroy .chart.c.f.$s.f.$ssrc
2439        }
2440        update
2441        .chart.c configure -scrollregion "0.0 0.0 [winfo width .chart.c.f] [winfo height .chart.c.f]"
2442}
2443
2444proc chart_label {ssrc label} {
2445        .chart.c.f.$ssrc.l configure -text $label
2446}
2447
2448proc chart_set {src dst val} {
2449        if {$val < 5} {
2450                set colour green
2451                set txtval "$val%"
2452        } elseif {$val < 10} {
2453                set colour orange
2454                set txtval "$val%"
2455        } elseif {$val <= 100} {
2456                set colour red
2457                set txtval "$val%"
2458        } else {
2459                set colour white
2460                set txtval { }
2461        }
2462        .chart.c.f.$src.f.$dst configure -background $colour -text "$txtval"
2463}
2464
2465proc chart_show {} {
2466        global matrix_on
2467        if {$matrix_on} {
2468                wm deiconify .chart
2469        } else {
2470                wm withdraw .chart
2471        }
2472}
2473
2474wm withdraw .chart
2475wm title    .chart "Reception quality matrix"
2476wm geometry .chart 320x200
2477wm protocol .chart WM_DELETE_WINDOW    {set matrix_on 0; chart_show}
2478
2479chart_show
2480
2481#
2482# End of RTCP RR chart routines
2483#
2484
2485#
2486# File Control Window
2487#
2488
2489set play_file(state) end
2490set rec_file(state) end
2491
2492catch {
2493    toplevel .file
2494    wm protocol .file WM_DELETE_WINDOW {set files_on 0; file_show}
2495    frame .file.play -relief groove -bd 2
2496    frame .file.rec  -relief groove -bd 2
2497    pack  .file.play -side top -pady 2 -padx 2 -fill x -expand 1
2498    pack  .file.rec  -side top -pady 2 -padx 2 -fill x -expand 1
2499   
2500    label .file.play.l -text "Playback"
2501    pack  .file.play.l -side top -fill x
2502    label .file.rec.l -text "Record"   
2503    pack  .file.rec.l -side top -fill x
2504
2505    button .file.dismiss -text Dismiss -command "set files_on 0; file_show"
2506    pack   .file.dismiss -side bottom -anchor e -padx 2 -pady 2
2507   
2508    wm withdraw .file
2509    wm title    .file "RAT File Control"
2510   
2511    foreach action { play rec } {
2512        frame  .file.$action.buttons
2513        pack   .file.$action.buttons
2514        button .file.$action.buttons.disk -bitmap disk -command "fileDialog $action"
2515        pack   .file.$action.buttons.disk -side left -padx 2 -pady 2 -anchor n
2516       
2517        foreach cmd "$action pause stop" {
2518            button .file.$action.buttons.$cmd -bitmap $cmd -state disabled -command file_$action\_$cmd
2519            pack   .file.$action.buttons.$cmd -side left -padx 2 -pady 2 -anchor n -fill x
2520        }
2521
2522        label  .file.$action.buttons.status -text "No file selected." -width 16 -anchor w
2523        pack   .file.$action.buttons.status -side bottom -fill both -expand 1 -padx 2 -pady 2
2524    }
2525} fwinerr
2526
2527if {$fwinerr != {}} {
2528        puts stderr $fwinerr
2529}
2530
2531proc fileDialog {cmdbox} {
2532    global win32 tcl_platform
2533   
2534        set defaultExtension au
2535        set defaultLocation  .
2536
2537    switch -glob $tcl_platform(os) {
2538        SunOS    {
2539                if [file exists /usr/demo/SOUND/sounds] { set defaultLocation /usr/demo/SOUND/sounds }
2540                }
2541        Windows* {
2542                if [file exists C:/Windows/Media]       { set defaultLocation C:/Windows/Media }
2543                set defaultExtension wav
2544                }
2545        }
2546   
2547    set types {
2548                {"NeXT/Sun Audio files" "au"}
2549                {"Microsoft RIFF files" "wav"}
2550                {"All files"            "*"}
2551    }
2552   
2553    if {![string compare $cmdbox "play"]} {
2554                catch { asFileBox .playfilebox  -defaultextension $defaultExtension -command file_open_$cmdbox -directory $defaultLocation -extensions $types } asferror
2555    } else {
2556                catch { asFileBox .recfilebox   -defaultextension $defaultExtension -command file_open_$cmdbox  -extensions $types -force_extension 1 } asferror
2557    }
2558       
2559        if {$asferror != ""} {
2560                puts stderr asferror
2561        }
2562}
2563
2564proc file_show {} {
2565    global files_on
2566   
2567    if {$files_on} {
2568                wm deiconify .file
2569    } else {
2570                wm withdraw .file
2571    }
2572}
2573
2574proc file_play_live {} {
2575# Request heart beat to determine if file is valid
2576        mbus_send "R" audio.file.play.live ""
2577}
2578
2579proc file_rec_live {} {
2580# Request heart beat to determine if file is valid
2581        mbus_send "R" audio.file.record.live ""
2582}
2583
2584proc file_open_play {path} {
2585    global play_file
2586
2587    mbus_send "R" "audio.file.play.open" [mbus_encode_str $path]
2588    mbus_send "R" "audio.file.play.pause" 1
2589    set play_file(state) paused
2590    set play_file(name) $path
2591   
2592    # Test whether file is still playing/valid
2593    after 200 file_play_live
2594}
2595
2596proc file_open_rec {path} {
2597    global rec_file
2598
2599    mbus_send "R" "audio.file.record.open" [mbus_encode_str $path]
2600    mbus_send "R" "audio.file.record.pause" 1
2601
2602    set rec_file(state) paused
2603    set rec_file(name)  $path
2604
2605    # Test whether file is still recording/valid
2606    after 200 file_rec_live
2607}
2608
2609proc file_enable_play { } {
2610    .file.play.buttons.play   configure -state normal
2611    .file.play.buttons.pause  configure -state disabled
2612    .file.play.buttons.stop   configure -state disabled
2613    .file.play.buttons.status configure -text "Ready to play."
2614}       
2615
2616proc file_enable_record { } {
2617    .file.rec.buttons.rec configure -state normal
2618    .file.rec.buttons.pause  configure -state disabled
2619    .file.rec.buttons.stop   configure -state disabled
2620    .file.rec.buttons.status configure -text "Ready to record."
2621}
2622
2623proc file_play_play {} {
2624        global play_file
2625       
2626        catch {
2627                puts stderr $play_file(state)
2628                if {$play_file(state) == "paused"} {
2629                        mbus_send "R" "audio.file.play.pause" 0
2630                        puts stderr "unpaused"
2631                } else {
2632                        mbus_send "R" "audio.file.play.open" [mbus_encode_str $play_file(name)]
2633                        puts stderr "re-opening"
2634                }
2635                set play_file(state) play
2636        } pferr
2637
2638        if { $pferr != "play" } { puts stderr "pferr: $pferr" }
2639
2640        .file.play.buttons.play   configure -state disabled
2641        .file.play.buttons.pause  configure -state normal
2642        .file.play.buttons.stop   configure -state normal
2643        .file.play.buttons.status configure -text "Playing."
2644        after 200 file_play_live
2645}
2646
2647proc file_play_pause {} {
2648    global play_file
2649   
2650    .file.play.buttons.play   configure -state normal
2651    .file.play.buttons.pause  configure -state disabled
2652    .file.play.buttons.stop   configure -state normal
2653    .file.play.buttons.status configure -text "Paused."
2654    set play_file(state) paused
2655    mbus_send "R" "audio.file.play.pause" 1
2656}
2657
2658proc file_play_stop {} {
2659        global play_file
2660       
2661        set play_file(state) end
2662        file_enable_play
2663        mbus_send "R" "audio.file.play.stop" ""
2664}
2665
2666proc file_rec_rec {} {
2667        global rec_file
2668       
2669        catch {
2670                puts stderr $rec_file(state)
2671                if {$rec_file(state) == "paused"} {
2672                        mbus_send "R" "audio.file.record.pause" 0
2673                } else {
2674                        mbus_send "R" "audio.file.record.open" [mbus_encode_str $rec_file(name)]
2675                }
2676                set rec_file(state) record
2677        } prerr
2678
2679        if { $prerr != "record" } { puts stderr "prerr: $prerr" }
2680
2681        .file.rec.buttons.rec    configure -state disabled
2682        .file.rec.buttons.pause  configure -state normal
2683        .file.rec.buttons.stop   configure -state normal
2684        .file.rec.buttons.status configure -text "Recording."
2685        after 200 file_rec_live
2686}
2687
2688proc file_rec_pause {} {
2689    global rec_file
2690   
2691    .file.rec.buttons.rec    configure -state normal
2692    .file.rec.buttons.pause  configure -state disabled
2693    .file.rec.buttons.stop   configure -state normal
2694    .file.rec.buttons.status configure -text "Paused."
2695    set rec_file(state) paused
2696    mbus_send "R" "audio.file.record.pause" 1
2697}
2698
2699proc file_rec_stop {} {
2700        global rec_file
2701       
2702        set rec_file(state) end
2703        file_enable_record
2704        mbus_send "R" "audio.file.record.stop" ""
2705}
2706
2707#
2708# End of File Window routines
2709#
2710
2711proc show_help {window} {
2712        global help_text help_on help_id
2713        if {$help_on} {
2714                .help.text  configure -text $help_text($window)
2715                # Beware! Don't put the popup under the cursor! Else we get window enter
2716                # for .help and leave for $window, making us hide_help which removes the
2717                # help window, giving us a window enter for $window making us popup the
2718                # help again.....
2719                if {[winfo width $window] > [winfo height $window]} {
2720                    set xpos [expr [winfo pointerx $window] + 10]
2721                    set ypos [expr [winfo rooty    $window] + [winfo height $window] + 4]
2722                } else {
2723                    set xpos [expr [winfo rootx    $window] + [winfo width $window] + 4]
2724                    set ypos [expr [winfo pointery $window] + 10]
2725                }
2726               
2727                wm geometry  .help +$xpos+$ypos
2728                set help_id [after 100 wm deiconify .help]
2729                raise .help $window
2730        }
2731}
2732
2733proc hide_help {window} {
2734        global help_id help_on
2735        if {[info exists help_id]} {
2736                after cancel $help_id
2737        }
2738        wm withdraw .help
2739}
2740
2741proc add_help {window text} {
2742        global help_text
2743        set help_text($window)  $text
2744        bind $window <Enter>    "+show_help $window"
2745        bind $window <Leave>    "+hide_help $window"
2746}
2747
2748bind Entry   <KeyPress> "+hide_help %W"
2749toplevel .help       -bg black
2750label    .help.text  -bg lavender -justify left
2751pack .help.text -side top -anchor w -fill x
2752wm transient        .help .
2753wm withdraw         .help
2754wm overrideredirect .help true
2755
2756add_help .r.c.tx.au.pow.sli     "This slider controls the volume\nof the sound you send."
2757add_help .r.c.tx.au.port.l0     "Click to change input device."
2758add_help .r.c.tx.au.port.l2     "Click to change input device."
2759add_help .r.c.tx.net.on         "If this button is pushed in, you are are transmitting, and\nmay be\
2760        heard by other participants. Holding down the\nright mouse button in\
2761        any RAT window will temporarily\ntoggle the state of this button,\
2762        allowing for easy\npush-to-talk operation."
2763add_help .r.c.tx.au.pow.bar     "Indicates the loudness of the\nsound you are sending. If this\nis\
2764                         moving, you may be heard by\nthe other participants."
2765
2766add_help .r.c.rx.au.pow.sli     "This slider controls the volume\nof the sound you hear."
2767add_help .r.c.rx.au.port.l0     "Click to change output device."
2768add_help .r.c.rx.au.port.l2     "Click to change output device."
2769add_help .r.c.rx.au.pow.bar     "Indicates the loudness of the\nsound you are hearing."
2770add_help .r.c.rx.net.on         "If pushed in, reception is muted."
2771
2772add_help .l.f           "Name of the session, and the IP address, port\n&\
2773                         TTL used to transmit the audio data."
2774add_help .l.t           "The participants in this session with you at the top.\nClick on a name\
2775                         with the left mouse button to display\ninformation on that participant,\
2776                         and with the middle\nbutton to mute that participant (the right button\nwill\
2777                         toggle the transmission mute button, as usual)."
2778
2779add_help .st.opts       "Brings up another window allowing\nthe control of various options."
2780add_help .st.about      "Brings up another window displaying\ncopyright & author information."
2781add_help .st.quit       "Press to leave the session."
2782
2783# preferences help
2784add_help .prefs.m.f.m  "Click here to change the preference\ncategory."
2785set i .prefs.buttons
2786add_help $i.bye         "Cancel changes."
2787add_help $i.apply       "Apply changes."
2788#add_help $i.save        "Save and apply changes."
2789
2790# user help
2791set i .prefs.pane.personal.a.f.f.ents
2792add_help $i.name        "Enter your name for transmission\nto other participants."
2793add_help $i.email       "Enter your email address for transmission\nto other participants."
2794add_help $i.phone       "Enter your phone number for transmission\nto other participants."
2795add_help $i.loc         "Enter your location for transmission\nto other participants."
2796
2797#audio help
2798set i .prefs.pane.audio
2799add_help $i.dd.device.mdev "Selects preferred audio device."
2800add_help $i.dd.sampling.freq.mb \
2801                        "Sets the sampling rate of the audio device.\nThis changes the available codecs."
2802add_help $i.dd.sampling.ch_in.mb \
2803                        "Changes between mono and stereo audio input."
2804add_help $i.dd.cks.f.f.silence\
2805                         "Prevents silence from being transmitted when the speaker is silent\n\
2806                          and the input is unmuted."
2807add_help $i.dd.cks.f.f.agc       "Enables automatic control of the volume\nof the sound you send."
2808add_help $i.dd.cks.f.f.loop "Enables hardware for loopback of audio input."
2809add_help $i.dd.cks.f.f.suppress \
2810                         "Mutes microphone when playing audio."
2811
2812# transmission help
2813set i .prefs.pane.transmission
2814
2815add_help $i.dd.units.m  "Sets the duration of each packet sent.\nThere is a fixed per-packet\
2816                         overhead, so\nmaking this larger will reduce the total\noverhead.\
2817                                                 The effects of packet loss are\nmore noticable with large packets."
2818add_help $i.dd.pri.m    "Changes the primary audio compression\nscheme. The list is arranged\
2819                         with high-\nquality, high-bandwidth choices at the\ntop, and\
2820                                                 poor-quality, lower-bandwidth\nchoices at the bottom."
2821add_help $i.cc.van.rb   "Sets no channel coding."
2822add_help $i.cc.red.rb   "Piggybacks earlier units of audio into packets\n\
2823                         to protect against packet loss. Some audio\n\
2824                         tools (eg: vat-4.0) are not able to receive\n\
2825                         audio sent with this option."
2826add_help $i.cc.red.fc.m \
2827                        "Sets the format of the piggybacked data."
2828add_help $i.cc.red.u.m \
2829                        "Sets the offset of the piggybacked data."
2830add_help $i.cc.layer.fc.m  "Sets the number of discrete layers which will\nbe sent. You need\
2831                                                    to start RAT with the options\n-l n <address>/<port> <address>/<port>,\nwhere\
2832                                                    n is the number of layers and there is an\naddress and port for each layer.\
2833                                                        NB: this is only\nsupported by the WBS codec at present."
2834add_help $i.cc.int.fc.m \
2835                        "Sets the separation of adjacent units within\neach packet. Larger values correspond\
2836                         to longer\ndelays."
2837add_help $i.cc.int.zz.m "Number of compound units per packet."
2838add_help $i.cc.int.rb   "Enables interleaving which exchanges latency\n\
2839                         for protection against burst losses.  No other\n\
2840                         audio tools can decode this format (experimental)."
2841
2842# Reception Help
2843set i .prefs.pane.reception
2844add_help $i.r.m         "Sets the type of repair applied when packets are\nlost. The schemes\
2845                         are listed in order of increasing\ncomplexity and quality of repair."
2846add_help $i.r.ms        "Sets the type of sample rate conversion algorithm\n\
2847                         that will be applied to streams that differ in rate\n\
2848                         to the audio device rate."
2849add_help $i.o.f.cb      "Enforce playout delay limits set below.\nThis is not usually desirable."
2850add_help $i.o.f.fl.scmin   "Sets the minimum playout delay that will be\napplied to incoming\
2851                         audio streams."
2852add_help $i.o.f.fr.scmax   "Sets the maximum playout delay that will be\napplied to incoming\
2853                         audio streams."
2854add_help $i.c.f.f.lec   "If enabled, extra delay is added at both sender and receiver.\nThis allows\
2855                         the receiver to better cope with host scheduling\nproblems, and the sender\
2856                         to perform better silence suppression.\nAs the name suggests, this option\
2857                         is intended for scenarios such\nas transmitting a lecture, where interactivity\
2858                         is less important\nthan quality."
2859
2860# security...too obvious for balloon help!
2861add_help .prefs.pane.security.a.f.f.e "Due to government export restrictions\nhelp\
2862                                       for this option is not available."
2863
2864# interface...ditto!
2865set i .prefs.pane.interface
2866add_help $i.a.f.f.power "Disable display of audio powermeters. This\nis only\
2867                         useful if you have a slow machine"
2868add_help $i.a.f.f.balloon "If you can see this, balloon help\nis enabled. If not, it isn't."
2869add_help $i.a.f.f.matrix  "Displays a chart showing the reception\nquality reported by all participants"
2870add_help $i.a.f.f.plist   "Hides the list of participants"
2871
2872add_help .chart         "This chart displays the reception quality reported\n by all session\
2873                         participants. Looking along a row\n gives the quality with which that\
2874                         participant was\n received by all other participants in the session:\n green\
2875                         is good quality, orange medium quality, and\n red poor quality audio."
2876
2877} script_error
2878
2879if { $script_error != "" } {
2880    puts "Error: \"$script_error\""
2881    destroy .
2882    exit -1
2883}
2884
2885wm deiconify .
Note: See TracBrowser for help on using the browser.