root/rat/trunk/ui_audiotool.tcl @ 3213

Revision 3213, 98.2 KB (checked in by ucacoxh, 14 years ago)

- balloon help checkbutton was disgusting. Perhaps bitmap checkbuttons are better.
- added reception and file boxes too.

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