root/rat/trunk/ui_audiotool.tcl @ 3212

Revision 3212, 98.0 KB (checked in by ucaccsp, 14 years ago)

Move handling of VOXLETDIR environment variable into the media engine.

  • 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
1519checkbutton .st.help -highlightthickness 0 -text "Balloon help" -onvalue 1 -offvalue 0 -variable help_on -font $compfont -anchor w -padx 4
1520button      .st.opts  -text "Options..." -command {wm deiconify .prefs; update_user_panel; raise .prefs}
1521button      .st.about -text "About..."   -command {jiggle_credits; wm deiconify .about}
1522button      .st.quit  -text "Quit"       -command do_quit
1523
1524frame .r.c -bd 0
1525frame .r.c.rx -relief groove -bd 2
1526frame .r.c.tx -relief groove -bd 2
1527
1528pack .st -side bottom -fill x -padx 2 -pady 0
1529pack .st.help -side left -fill both -expand 1
1530
1531pack .st.quit .st.about .st.opts -side right -anchor w -padx 2 -pady 2
1532
1533pack .r -side top -fill x -padx 2
1534pack .r.c -side top -fill x -expand 1
1535pack .r.c.rx -side left -fill x -expand 1
1536pack .r.c.tx -side left -fill x -expand 1
1537
1538pack .l -side top -fill both -expand 1
1539pack .l.f -side bottom -fill x -padx 2 -pady 2
1540pack .l.f.title .l.f.addr -side top -pady 2 -anchor w -fill x
1541pack .l.t  -side top -fill both -expand 1 -padx 2
1542pack .l.t.scr -side left -fill y
1543pack .l.t.list -side left -fill both -expand 1
1544bind .l.t.list <Configure> {fix_scrollbar}
1545
1546# Device output controls
1547set out_mute_var 0
1548frame .r.c.rx.net
1549frame .r.c.rx.au
1550
1551pack .r.c.rx.net -side top -anchor n -fill both
1552pack .r.c.rx.au -side bottom -expand 1 -fill both
1553
1554checkbutton .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
1555label       .r.c.rx.net.bw -textv bps_in -font $compfont -anchor e
1556pack .r.c.rx.net.on -side left
1557pack .r.c.rx.net.bw -side right -fill x -expand 1
1558
1559frame  .r.c.rx.au.port -bd 0
1560button .r.c.rx.au.port.l0 -highlightthickness 0 -command {incr_port oport oports -1} -font $compfont -bitmap left -relief flat
1561label  .r.c.rx.au.port.l1 -highlightthickness 0 -textv oport -font $compfont -width 10
1562button .r.c.rx.au.port.l2 -highlightthickness 0 -command {incr_port oport oports +1} -font $compfont -bitmap right -relief flat
1563pack   .r.c.rx.au.port -side top -fill x -expand 1
1564pack   .r.c.rx.au.port.l0 -side left -fill y
1565pack   .r.c.rx.au.port.l1 -side left -fill x -expand 1
1566pack   .r.c.rx.au.port.l2 -side left -fill y
1567
1568frame  .r.c.rx.au.pow -relief sunk -bd 2
1569bargraphCreate .r.c.rx.au.pow.bar
1570scale .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
1571pack .r.c.rx.au.pow .r.c.rx.au.pow.bar .r.c.rx.au.pow.sli -side top -fill both -expand 1
1572
1573# Device input controls
1574set in_mute_var 1
1575
1576frame .r.c.tx.net
1577frame .r.c.tx.au
1578
1579pack .r.c.tx.net -side top -anchor n  -fill both
1580pack .r.c.tx.au -side bottom -expand 1 -fill both
1581
1582checkbutton .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
1583label       .r.c.tx.net.bw -textv bps_out -font $compfont -anchor e
1584pack .r.c.tx.net.on -side left
1585pack .r.c.tx.net.bw -side right -fill x -expand 1
1586
1587frame  .r.c.tx.au.port -bd 0
1588button .r.c.tx.au.port.l0 -highlightthickness 0 -command {incr_port iport iports -1} -font $compfont -bitmap left -relief flat
1589label  .r.c.tx.au.port.l1 -highlightthickness 0 -textv iport -font $compfont -width 10
1590button .r.c.tx.au.port.l2 -highlightthickness 0 -command {incr_port iport iports +1} -font $compfont -bitmap right -relief flat
1591pack   .r.c.tx.au.port -side top -fill x -expand 1
1592pack   .r.c.tx.au.port.l0 -side left -fill y
1593pack   .r.c.tx.au.port.l1 -side left -fill x -expand 1
1594pack   .r.c.tx.au.port.l2 -side left -fill y
1595
1596frame  .r.c.tx.au.pow -relief sunk -bd 2
1597bargraphCreate .r.c.tx.au.pow.bar
1598scale .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
1599pack .r.c.tx.au.pow .r.c.tx.au.pow.bar .r.c.tx.au.pow.sli -side top -fill both -expand 1
1600
1601bind all <ButtonPress-3>   {toggle in_mute_var; input_mute $in_mute_var}
1602bind all <ButtonRelease-3> {toggle in_mute_var; input_mute $in_mute_var}
1603bind all <q>               {+if {[winfo class %W] != "Entry"} {do_quit}}
1604
1605# Override default tk behaviour
1606wm protocol . WM_DELETE_WINDOW do_quit
1607wm title    . Initializing...
1608
1609if {$win32 == 0} {
1610        wm iconbitmap . rat_small
1611}
1612#wm resizable . 0 1
1613if ([info exists geometry]) {
1614        wm geometry . $geometry
1615}
1616
1617proc averageCharacterWidth {font} {
1618    set sample "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
1619    set slen [string length $sample]
1620    set wpc  [expr [font measure $font $sample] / $slen + 1]
1621    return $wpc
1622}
1623
1624# constrain_window - window, font, characters wide, characters high
1625proc constrain_window {w font cW cH} {
1626   
1627    catch {
1628            set wpc [averageCharacterWidth $font]
1629            set hpc [font metrics $font -ascent]
1630   
1631        # Calculate dimensions
1632            set width [expr $cW * $wpc]
1633            set height [expr $cH * $hpc]
1634            wm geometry $w [format "%sx%s" $width $height]
1635            set dummy ""
1636    } err
1637    if {$err != ""} {
1638        puts "Error: $err"
1639    }
1640}
1641
1642proc tk_optionCmdMenu {w varName firstValue args} {
1643    upvar #0 $varName var
1644 
1645    if ![info exists var] {
1646        set var $firstValue
1647    }
1648    menubutton $w -textvariable $varName -indicatoron 1 -menu $w.menu \
1649            -relief raised -bd 2 -highlightthickness 2 -anchor c
1650
1651    menu $w.menu -tearoff 0
1652    $w.menu add command -label $firstValue -command "set $varName \"$firstValue\""
1653    foreach i $args {
1654        $w.menu add command -label $i -command "set $varName \"$i\""
1655    }
1656    return $w.menu
1657}
1658
1659
1660###############################################################################
1661# Preferences Panel
1662#
1663
1664set prefs_pane "Personal"
1665toplevel .prefs
1666wm title .prefs "Preferences"
1667wm resizable .prefs 0 0
1668wm withdraw  .prefs
1669
1670frame .prefs.m
1671pack .prefs.m -side top -fill x -expand 0 -padx 2 -pady 2
1672frame .prefs.m.f
1673pack .prefs.m.f -padx 0 -pady 0
1674label .prefs.m.f.t -text "Category: "
1675pack .prefs.m.f.t -pady 2 -side left
1676menubutton .prefs.m.f.m -menu .prefs.m.f.m.menu -indicatoron 1 -textvariable prefs_pane -relief raised -width 14
1677pack .prefs.m.f.m -side top
1678menu .prefs.m.f.m.menu -tearoff 0
1679.prefs.m.f.m.menu add command -label "Personal"     -command {set_pane prefs_pane .prefs.pane "Personal"}
1680.prefs.m.f.m.menu add command -label "Transmission" -command {set_pane prefs_pane .prefs.pane "Transmission"; update_codecs_displayed}
1681.prefs.m.f.m.menu add command -label "Reception"    -command {set_pane prefs_pane .prefs.pane "Reception"}
1682.prefs.m.f.m.menu add command -label "Audio"        -command {set_pane prefs_pane .prefs.pane "Audio"}
1683.prefs.m.f.m.menu add command -label "Codecs"        -command {set_pane prefs_pane .prefs.pane "Codecs"; codecs_panel_fill}
1684.prefs.m.f.m.menu add command -label "Security"     -command {set_pane prefs_pane .prefs.pane "Security"}
1685.prefs.m.f.m.menu add command -label "Interface"    -command {set_pane prefs_pane .prefs.pane "Interface"}
1686
1687frame  .prefs.buttons
1688pack   .prefs.buttons       -side bottom -fill x
1689button .prefs.buttons.bye   -text "Cancel" -command {sync_ui_to_engine; wm withdraw .prefs}
1690button .prefs.buttons.apply -text "Apply" -command {wm withdraw .prefs; sync_engine_to_ui}
1691pack   .prefs.buttons.bye .prefs.buttons.apply -side right -padx 2 -pady 2
1692
1693wm protocol .prefs WM_DELETE_WINDOW {sync_ui_to_engine; wm withdraw .prefs}
1694
1695frame .prefs.pane -relief groove -bd 2
1696pack  .prefs.pane -side left -fill both -expand 1 -padx 4 -pady 2
1697
1698# setup width of prefs panel
1699constrain_window .prefs $infofont 56 30
1700
1701# Personal Info Pane ##########################################################
1702set i .prefs.pane.personal
1703frame $i
1704pack $i -fill both -expand 1 -pady 2 -padx 2
1705
1706frame $i.a
1707frame $i.a.f -rel fl
1708pack $i.a -side top -fill both -expand 1
1709pack $i.a.f -side left -fill x -expand 1
1710
1711frame $i.a.f.f -rel fl
1712pack $i.a.f.f
1713
1714label $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
1715pack $i.a.f.f.l -side top -anchor w -fill x
1716
1717frame $i.a.f.f.lbls
1718frame $i.a.f.f.ents
1719pack  $i.a.f.f.lbls -side left -fill y
1720pack  $i.a.f.f.ents -side right
1721
1722label $i.a.f.f.lbls.1  -text "Name:"     -anchor w
1723label $i.a.f.f.lbls.2 -text "Email:"    -anchor w
1724label $i.a.f.f.lbls.3 -text "Phone:"    -anchor w
1725label $i.a.f.f.lbls.4   -text "Location:" -anchor w
1726label $i.a.f.f.lbls.5  -text "Note:" -anchor w
1727pack $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
1728
1729entry $i.a.f.f.ents.name -width 28 -highlightthickness 0 -textvariable rtcp_name
1730entry $i.a.f.f.ents.email -width 28 -highlightthickness 0 -textvariable rtcp_email
1731entry $i.a.f.f.ents.phone -width 28 -highlightthickness 0 -textvariable rtcp_phone
1732entry $i.a.f.f.ents.loc  -width 28 -highlightthickness 0 -textvariable rtcp_loc
1733entry $i.a.f.f.ents.note  -width 28 -highlightthickness 0 -textvariable rtcp_note
1734pack $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
1735
1736proc update_user_panel {} {
1737    global my_ssrc NAME EMAIL PHONE LOC NOTE
1738    global rtcp_name rtcp_email rtcp_phone rtcp_loc rtcp_note
1739    if {[info exists my_ssrc]} {
1740        set rtcp_name  $NAME($my_ssrc)
1741        set rtcp_email $EMAIL($my_ssrc)
1742        set rtcp_phone $PHONE($my_ssrc)
1743        set rtcp_loc   $LOC($my_ssrc)
1744        set rtcp_note  $NOTE($my_ssrc)
1745    }
1746}
1747
1748# Transmission Pane ###########################################################
1749set i .prefs.pane.transmission
1750frame $i
1751frame $i.dd
1752frame $i.cc
1753frame $i.cc.van
1754frame $i.cc.red
1755frame $i.cc.layer
1756frame $i.cc.int
1757label $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."
1758frame $i.title1-f -relief raised
1759label $i.title1-f.l -text "Audio Encoding"
1760pack $i.intro $i.title1-f $i.title1-f.l $i.dd -side top -fill x
1761
1762#pack $i.dd -fill x -side top -anchor n
1763
1764frame $i.title2-f -relief raised
1765label $i.title2-f.l -text "Channel Coding Options"
1766pack $i.title2-f $i.title2-f.l -fill x -side top
1767pack $i.cc -fill x -anchor w -pady 1
1768
1769pack $i.cc.van $i.cc.red $i.cc.layer -fill x -anchor w -pady 0
1770# interleaving panel $i.cc.int not packed since interleaving isn't support in this release
1771frame $i.dd.units
1772frame $i.dd.pri
1773
1774pack $i.dd.units $i.dd.pri -side right -fill x
1775
1776label $i.dd.pri.l -text "Encoding:"
1777menubutton $i.dd.pri.m -menu $i.dd.pri.m.menu -indicatoron 1 -textvariable prenc -relief raised -width 13
1778pack $i.dd.pri.l $i.dd.pri.m -side top
1779# fill in codecs
1780menu $i.dd.pri.m.menu -tearoff 0
1781
1782label $i.dd.units.l -text "Units:"
1783tk_optionCmdMenu $i.dd.units.m upp 1 2 4 8
1784$i.dd.units.m configure -width 13 -highlightthickness 0 -bd 1
1785pack $i.dd.units.l $i.dd.units.m -side top -fill x
1786
1787radiobutton $i.cc.van.rb -text "No Loss Protection" -justify right -value none        -variable channel_var
1788radiobutton $i.cc.red.rb -text "Redundancy"         -justify right -value redundancy  -variable channel_var
1789radiobutton $i.cc.layer.rb -text "Layering"                     -justify right -value layering    -variable channel_var
1790radiobutton $i.cc.int.rb -text "Interleaving"       -justify right -value interleaved -variable channel_var -state disabled
1791pack $i.cc.van.rb $i.cc.red.rb $i.cc.layer.rb $i.cc.int.rb -side left -anchor nw -padx 2
1792
1793frame $i.cc.red.fc
1794label $i.cc.red.fc.l -text "Encoding:"
1795menubutton $i.cc.red.fc.m -textvariable secenc -indicatoron 1 -menu $i.cc.red.fc.m.menu -relief raised -width 13
1796menu $i.cc.red.fc.m.menu -tearoff 0
1797
1798frame $i.cc.red.u
1799label $i.cc.red.u.l -text "Offset in Pkts:"
1800tk_optionCmdMenu $i.cc.red.u.m red_off "1" "2" "4" "8" 
1801$i.cc.red.u.m configure -width 13 -highlightthickness 0 -bd 1
1802pack $i.cc.red.u -side right -anchor e -fill y
1803pack $i.cc.red.u.l $i.cc.red.u.m -fill x
1804pack $i.cc.red.fc -side right
1805pack $i.cc.red.fc.l $i.cc.red.fc.m
1806
1807frame $i.cc.layer.fc
1808label $i.cc.layer.fc.l -text "Layers:"
1809menubutton $i.cc.layer.fc.m -textvariable layerenc -indicatoron 1 -menu $i.cc.layer.fc.m.menu -relief raised -width 13
1810menu $i.cc.layer.fc.m.menu -tearoff 0
1811pack $i.cc.layer.fc -side right
1812pack $i.cc.layer.fc.l $i.cc.layer.fc.m
1813
1814frame $i.cc.int.zz
1815label $i.cc.int.zz.l -text "Units:"
1816tk_optionCmdMenu $i.cc.int.zz.m int_units 2 4 6 8
1817$i.cc.int.zz.m configure -width 13 -highlightthickness 0 -bd 1 -state disabled
1818
1819frame $i.cc.int.fc
1820label $i.cc.int.fc.l -text "Separation:" 
1821tk_optionCmdMenu $i.cc.int.fc.m int_gap 2 4 6 8
1822$i.cc.int.fc.m configure -width 13 -highlightthickness 0 -bd 1 -state disabled
1823
1824pack $i.cc.int.fc $i.cc.int.zz -side right
1825pack $i.cc.int.fc.l $i.cc.int.fc.m -fill x -expand 1
1826pack $i.cc.int.zz.l $i.cc.int.zz.m -fill x -expand 1
1827
1828# Reception Pane ##############################################################
1829set i .prefs.pane.reception
1830frame $i 
1831frame $i.r -rel f
1832frame $i.o -rel f
1833frame $i.c -rel f
1834pack $i.r -side top -fill x -pady 0 -ipady 1
1835pack $i.o -side top -fill both  -pady 1
1836pack $i.c -side top -fill both  -pady 1 -expand 1
1837label $i.r.l -text "Repair Scheme:"
1838tk_optionCmdMenu $i.r.m repair_var {}
1839
1840label $i.r.ls -text "Sample Rate Conversion"
1841tk_optionCmdMenu $i.r.ms convert_var {}
1842
1843$i.r.m  configure -width 20 -bd 1
1844$i.r.ms configure -width 20 -bd 1
1845pack $i.r.l $i.r.m $i.r.ls $i.r.ms -side top
1846
1847frame $i.o.f
1848checkbutton $i.o.f.cb -text "Limit Playout Delay" -variable limit_var
1849frame $i.o.f.fl
1850label $i.o.f.fl.l1 -text "Minimum Delay (ms)" 
1851scale $i.o.f.fl.scmin -orient horizontal -from 0 -to 1000    -variable min_var -font $smallfont
1852frame $i.o.f.fr
1853label $i.o.f.fr.l2 -text "Maximum Delay (ms)"           
1854scale $i.o.f.fr.scmax -orient horizontal -from 1000 -to 2000 -variable max_var -font $smallfont
1855pack $i.o.f
1856pack $i.o.f.cb -side top -fill x
1857pack $i.o.f.fl $i.o.f.fr -side left
1858pack $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
1859
1860frame $i.c.f
1861frame $i.c.f.f
1862checkbutton $i.c.f.f.lec -text "Lecture Mode"       -variable lecture_var
1863checkbutton $i.c.f.f.ext -text "3D Audio Rendering" -variable 3d_audio_var
1864
1865pack $i.c.f -fill x -side left -expand 1
1866pack $i.c.f.f
1867pack $i.c.f.f.lec -side top  -anchor w
1868pack $i.c.f.f.ext -side top  -anchor w
1869
1870# Audio #######################################################################
1871set i .prefs.pane.audio
1872frame $i 
1873frame $i.dd -rel fl
1874pack $i.dd -fill both -expand 1 -anchor w -pady 1
1875
1876label $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
1877pack $i.dd.title -fill x
1878
1879frame $i.dd.device
1880pack $i.dd.device -side top
1881
1882label $i.dd.device.l -text "Audio Device:"
1883pack  $i.dd.device.l -side top -fill x
1884menubutton $i.dd.device.mdev -menu $i.dd.device.mdev.menu -indicatoron 1 \
1885                                -textvariable audio_device -relief raised -width 5
1886pack $i.dd.device.mdev -fill x -expand 1
1887menu $i.dd.device.mdev.menu -tearoff 0
1888
1889frame $i.dd.sampling 
1890pack  $i.dd.sampling
1891
1892frame $i.dd.sampling.freq
1893frame $i.dd.sampling.ch_in
1894pack $i.dd.sampling.freq $i.dd.sampling.ch_in -side left -fill x
1895
1896label $i.dd.sampling.freq.l   -text "Sample Rate:   "
1897label $i.dd.sampling.ch_in.l  -text "Channels:"
1898pack $i.dd.sampling.freq.l $i.dd.sampling.ch_in.l -fill x
1899
1900menubutton $i.dd.sampling.freq.mb -menu $i.dd.sampling.freq.mb.m -indicatoron 1 \
1901                                  -textvariable freq -relief raised
1902pack $i.dd.sampling.freq.mb -side left -fill x -expand 1
1903menu $i.dd.sampling.freq.mb.m
1904
1905menubutton $i.dd.sampling.ch_in.mb -menu $i.dd.sampling.ch_in.mb.m -indicatoron 1 \
1906                                  -textvariable ichannels -relief raised
1907pack $i.dd.sampling.ch_in.mb -side left -fill x -expand 1
1908menu $i.dd.sampling.ch_in.mb.m
1909
1910frame $i.dd.cks
1911pack $i.dd.cks -fill both -expand 1
1912frame $i.dd.cks.f
1913frame $i.dd.cks.f.f
1914checkbutton $i.dd.cks.f.f.silence  -text "Silence Suppression"    -variable silence_var
1915checkbutton $i.dd.cks.f.f.agc      -text "Automatic Gain Control" -variable agc_var
1916checkbutton $i.dd.cks.f.f.loop     -text "Audio Loopback"         -variable audio_loop_var
1917checkbutton $i.dd.cks.f.f.suppress -text "Echo Suppression"       -variable echo_var
1918pack $i.dd.cks.f -fill x -side top -expand 1
1919pack $i.dd.cks.f.f
1920pack $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
1921
1922# Codecs pane #################################################################
1923set i .prefs.pane.codecs
1924frame $i 
1925
1926
1927frame $i.of -rel fl
1928pack  $i.of -fill both -expand 1 -anchor w -pady 1 -side top
1929
1930message $i.of.l -width 30c -justify left -text "This panel shows available codecs and allows RTP payload re-mapping." 
1931pack $i.of.l -side top -fill x
1932
1933frame   $i.of.codecs
1934
1935pack    $i.of.codecs -side left -padx 2 -fill y
1936frame   $i.of.codecs.l -rel raised
1937label   $i.of.codecs.l.l -text "Codec"
1938listbox $i.of.codecs.lb -width 20 -yscrollcommand "$i.of.codecs.scroll set" -relief fl -bg white
1939scrollbar $i.of.codecs.scroll -command "$i.of.codecs.lb yview" -rel fl
1940pack    $i.of.codecs.l $i.of.codecs.l.l -side top -fill x
1941pack    $i.of.codecs.scroll $i.of.codecs.lb -side left -fill both
1942
1943frame   $i.of.details -bd 0
1944pack    $i.of.details -side left -fill both -expand 1 -anchor n
1945
1946frame $i.of.details.upper
1947pack $i.of.details.upper -fill x
1948
1949frame $i.of.details.desc
1950pack $i.of.details.desc -side top -fill x
1951
1952frame $i.of.details.pt
1953pack $i.of.details.pt -side bottom -fill x -anchor s
1954label $i.of.details.pt.l -anchor w -text "RTP payload:"
1955pack  $i.of.details.pt.l -side left -anchor w
1956
1957entry $i.of.details.pt.e -width 4
1958pack  $i.of.details.pt.e -side left -padx 4
1959
1960button $i.of.details.pt.b -text "Map Codec" -command map_codec
1961pack  $i.of.details.pt.b -side right -padx 4
1962
1963frame $i.of.details.upper.l0 -relief raised
1964label $i.of.details.upper.l0.l -text "Details"
1965pack $i.of.details.upper.l0 $i.of.details.upper.l0.l -side top -fill x -expand 1
1966
1967frame $i.of.details.upper.l
1968pack $i.of.details.upper.l -side left
1969label $i.of.details.upper.l.0 -text "Short name:"  -anchor w
1970label $i.of.details.upper.l.1 -text "Sample Rate (Hz):" -anchor w
1971label $i.of.details.upper.l.2 -text "Channels:"    -anchor w
1972label $i.of.details.upper.l.3 -text "Bitrate (kbps):"     -anchor w
1973label $i.of.details.upper.l.4 -text "RTP Payload:" -anchor w
1974label $i.of.details.upper.l.5 -text "Capability:" -anchor w
1975label $i.of.details.upper.l.6 -text "Layers:" -anchor w
1976
1977for {set idx 0} {$idx < 7} {incr idx} {
1978    pack $i.of.details.upper.l.$idx -side top -fill x
1979}
1980
1981frame $i.of.details.upper.r
1982pack $i.of.details.upper.r -side left -fill x -expand 1
1983label $i.of.details.upper.r.0 -anchor w
1984label $i.of.details.upper.r.1 -anchor w
1985label $i.of.details.upper.r.2 -anchor w
1986label $i.of.details.upper.r.3 -anchor w
1987label $i.of.details.upper.r.4 -anchor w
1988label $i.of.details.upper.r.5 -anchor w
1989label $i.of.details.upper.r.6 -anchor w
1990
1991for {set idx 0} {$idx < 7} {incr idx} {
1992    pack $i.of.details.upper.r.$idx -side top -fill x
1993}
1994
1995set descw [expr [averageCharacterWidth $infofont] * 30]
1996label $i.of.details.desc.l -text "Description:" -anchor w -wraplength $descw -justify left
1997pack $i.of.details.desc.l -side left -fill x
1998unset descw
1999
2000bind $i.of.codecs.lb <1> {
2001    codecs_panel_select [%W index @%x,%y]
2002}
2003
2004bind $i.of.codecs.lb <ButtonRelease-1> {
2005    codecs_panel_select [%W index @%x,%y]
2006}
2007proc codecs_panel_fill {} {
2008    global codecs
2009
2010    .prefs.pane.codecs.of.codecs.lb delete 0 end
2011
2012    foreach {c} $codecs {
2013        .prefs.pane.codecs.of.codecs.lb insert end $c
2014    }
2015}
2016
2017set last_selected_codec -1
2018
2019proc codecs_panel_select { idx } {
2020    global codecs codec_nick_name codec_rate codec_channels codec_pt codec_block_size codec_data_size codec_desc codec_caps codec_layers
2021    global last_selected_codec
2022
2023    set last_selected_codec $idx
2024
2025    set codec [lindex $codecs $idx]
2026    set root  .prefs.pane.codecs.of.details.upper.r
2027    $root.0 configure -text $codec_nick_name($codec)
2028    $root.1 configure -text $codec_rate($codec)
2029    $root.2 configure -text $codec_channels($codec)
2030
2031    set fps [expr $codec_rate($codec) * 2 * $codec_channels($codec) / $codec_block_size($codec) ]
2032    set kbps [expr 8 * $fps * $codec_data_size($codec) / 1000.0]
2033    $root.3 configure -text [format "%.1f" $kbps]
2034
2035    $root.4 configure -text $codec_pt($codec)
2036    $root.5 configure -text $codec_caps($codec)
2037    $root.6 configure -text $codec_layers($codec)
2038   
2039    .prefs.pane.codecs.of.details.desc.l configure -text "Description: $codec_desc($codec)"
2040
2041}
2042
2043proc map_codec {} {
2044    global codecs last_selected_codec
2045
2046    set idx $last_selected_codec
2047
2048    if {$last_selected_codec == -1} {
2049        return
2050    }
2051
2052    set pt [.prefs.pane.codecs.of.details.pt.e get]
2053    .prefs.pane.codecs.of.details.pt.e delete 0 end
2054
2055    set ptnot [string trim $pt 1234567890]
2056    if {$ptnot != ""} {
2057        return
2058    }
2059
2060    set codec [lindex $codecs $idx]
2061
2062    mbus_send "R" "tool.rat.payload.set" "[mbus_encode_str $codec] $pt"
2063    after 1000 codecs_panel_select $idx
2064}
2065
2066# Security Pane ###############################################################
2067set i .prefs.pane.security
2068frame $i 
2069frame $i.a -rel fl
2070frame $i.a.f
2071frame $i.a.f.f
2072label $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."
2073pack $i.a.f.f.l
2074pack $i.a -side top -fill both -expand 1
2075label $i.a.f.f.lbl -text "Key:"
2076entry $i.a.f.f.e -width 28 -textvariable key
2077checkbutton $i.a.f.f.cb -text "Enabled" -variable key_var
2078pack $i.a.f -fill x -side left -expand 1
2079pack $i.a.f.f
2080pack $i.a.f.f.lbl $i.a.f.f.e $i.a.f.f.cb -side left -pady 4 -padx 2 -fill x
2081
2082# Interface Pane ##############################################################
2083set i .prefs.pane.interface
2084frame $i 
2085frame $i.a -rel fl
2086frame $i.a.f
2087frame $i.a.f.f
2088label $i.a.f.f.l -anchor w -justify left -text "The following features may be\ndisabled to conserve processing\npower."
2089pack $i.a -side top -fill both -expand 1
2090pack $i.a.f -fill x -side left -expand 1
2091checkbutton $i.a.f.f.power   -text "Powermeters active"       -variable meter_var
2092checkbutton $i.a.f.f.balloon -text "Balloon help"             -variable help_on
2093checkbutton $i.a.f.f.matrix  -text "Reception quality matrix" -variable matrix_on -command chart_show
2094checkbutton $i.a.f.f.plist   -text "Participant list"         -variable plist_on  -command toggle_plist
2095checkbutton $i.a.f.f.fwin    -text "File Control Window"      -variable files_on  -command file_show
2096pack $i.a.f.f $i.a.f.f.l
2097pack $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
2098
2099proc set_pane {p base desc} {
2100    upvar 1 $p pane
2101    set tpane [string tolower [lindex [split $pane] 0]]
2102    pack forget $base.$tpane
2103    set tpane [string tolower [lindex [split $desc] 0]]
2104    pack $base.$tpane -fill both -expand 1 -padx 2 -pady 2
2105    set pane $desc
2106}
2107
2108# Initialise "About..." toplevel window
2109toplevel   .about
2110frame      .about.rim -relief groove -bd 2
2111frame      .about.m
2112frame      .about.rim.d
2113pack .about.m -fill x
2114pack .about.rim -padx 4 -pady 2 -side top -fill both -expand 1
2115pack .about.rim.d -side top -fill both -expand 1
2116
2117frame .about.m.f
2118label .about.m.f.l -text "Category:"
2119menubutton .about.m.f.mb -menu .about.m.f.mb.menu -indicatoron 1 -textvariable about_pane -relief raised -width 10
2120menu .about.m.f.mb.menu -tearoff 0
2121.about.m.f.mb.menu add command -label "Credits"   -command {set_pane about_pane .about.rim.d "Credits"   }
2122.about.m.f.mb.menu add command -label "Feedback"  -command {set_pane about_pane .about.rim.d "Feedback"  }
2123.about.m.f.mb.menu add command -label "Copyright" -command {set_pane about_pane .about.rim.d "Copyright" }
2124
2125pack .about.m.f
2126pack .about.m.f.l .about.m.f.mb -side left
2127
2128frame     .about.rim.d.copyright
2129frame     .about.rim.d.copyright.f -relief flat
2130frame     .about.rim.d.copyright.f.f
2131text      .about.rim.d.copyright.f.f.blurb -height 14 -yscrollcommand ".about.rim.d.copyright.f.f.scroll set" -relief flat -bg white
2132scrollbar .about.rim.d.copyright.f.f.scroll -command ".about.rim.d.copyright.f.f.blurb yview" -relief flat
2133
2134pack      .about.rim.d.copyright.f -expand 1 -fill both
2135pack      .about.rim.d.copyright.f.f -expand 1 -fill both
2136pack      .about.rim.d.copyright.f.f.scroll -side left -fill y -expand 1
2137pack      .about.rim.d.copyright.f.f.blurb -side left -fill y -expand 1
2138
2139frame     .about.rim.d.credits
2140frame     .about.rim.d.credits.f -relief flat
2141frame     .about.rim.d.credits.f.f
2142pack      .about.rim.d.credits.f -fill both -expand 1
2143pack      .about.rim.d.credits.f.f -side left -fill x -expand 1
2144label     .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:"
2145label     .about.rim.d.credits.f.f.2 -foreground blue -text Good
2146label     .about.rim.d.credits.f.f.3                  -text "Development Team:"
2147label     .about.rim.d.credits.f.f.4 -foreground blue -text Bad
2148label     .about.rim.d.credits.f.f.5                  -text "Additional Contributions:"
2149label     .about.rim.d.credits.f.f.6 -foreground blue -text Ugly
2150for {set i 1} {$i<=6} {incr i} {
2151    pack  .about.rim.d.credits.f.f.$i -side top -fill x -anchor n
2152}
2153
2154frame     .about.rim.d.feedback
2155frame     .about.rim.d.feedback.f -relief flat
2156frame     .about.rim.d.feedback.f.f
2157pack      .about.rim.d.feedback.f -fill both -expand 1
2158pack      .about.rim.d.feedback.f.f -side left -fill x -expand 1
2159label     .about.rim.d.feedback.f.f.1                  -text "Comments, suggestions, and bug-reports should be sent to:"
2160label     .about.rim.d.feedback.f.f.2 -foreground blue -text "rat-trap@cs.ucl.ac.uk\n"
2161label     .about.rim.d.feedback.f.f.3                  -text "Further information is available on the world-wide web at:"
2162label     .about.rim.d.feedback.f.f.4 -foreground blue -text "http://www-mice.cs.ucl.ac.uk/multimedia/software/rat/\n"
2163for {set i 1} {$i<=4} {incr i} {
2164    pack  .about.rim.d.feedback.f.f.$i -side top -fill x
2165}
2166
2167wm withdraw  .about
2168wm title     .about "About RAT"
2169wm resizable .about 0 0
2170wm protocol  .about WM_DELETE_WINDOW {wm withdraw .about}
2171
2172set about_pane Copyright
2173set_pane about_pane .about.rim.d "Credits" 
2174constrain_window .about $infofont 64 25
2175
2176.about.rim.d.copyright.f.f.blurb insert end \
2177{Copyright (C) 1995-2000 University College London
2178All rights reserved.
2179
2180Redistribution and use in source and binary forms, with or without
2181modification, is permitted provided that the following conditions
2182are met:
2183
21841. Redistributions of source code must retain the above copyright
2185   notice, this list of conditions and the following disclaimer.
2186
21872. Redistributions in binary form must reproduce the above copyright
2188   notice, this list of conditions and the following disclaimer in the
2189   documentation and/or other materials provided with the distribution.
2190
21913. All advertising materials mentioning features or use of this software
2192   must display the following acknowledgement:
2193
2194     This product includes software developed by the Computer Science
2195     Department at University College London.
2196
21974. Neither the name of the University nor of the Department may be used
2198   to endorse or promote products derived from this software without
2199   specific prior written permission.
2200
2201THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
2202``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
2203BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
2204AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
2205EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
2206DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2207CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2208PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2209DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2210AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2211LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2212ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2213ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2214
2215This software is derived, in part, from publically available
2216and contributed source code with the following copyright:
2217
2218Copyright (C) 1991-1993 Regents of the University of California
2219Copyright (C) 1992 Stichting Mathematisch Centrum, Amsterdam
2220Copyright (C) 1991-1992 RSA Data Security, Inc
2221Copyright (C) 1992 Jutta Degener and Carsten Bormann, TU Berlin
2222Copyright (C) 1994 Paul Stewart
2223Copyright (C) 1996 Regents of the University of California
2224Copyright (C) 2000 Nortel Networks
2225Copyright (C) 2000 Argonne National Laboratory
2226
2227This product includes software developed by the Computer
2228Systems Engineering Group and by the Network Research Group
2229at Lawrence Berkeley Laboratory.
2230
2231The WB-ADPCM algorithm was developed by British Telecommunications
2232plc.  Permission has been granted to use it for non-commercial
2233research and development projects.  BT retain the intellectual
2234property rights to this algorithm.
2235
2236Encryption features of this software use the RSA Data
2237Security, Inc. MD5 Message-Digest Algorithm.
2238
2239}
2240
2241proc shuffle_rats {args} {
2242    # This should really animate the movement and play fruit-machine sounds.... :-)
2243    set r ""
2244    set end [llength $args]
2245    set l 0
2246    while { $l < $end } {
2247        set toget [expr abs([clock clicks]) % [llength $args]]
2248        set r [format "%s%s  " $r [lindex $args $toget]]
2249        set args [lreplace $args $toget $toget]
2250        lappend used $toget
2251        if {$l >0 && [expr ($l + 1) % 3] == 0} {
2252            set r "$r\n"
2253        }
2254        incr l
2255    }
2256    return $r
2257}
2258
2259proc jiggle_credits {} {
2260# Software really developed by the Socialist Department of Computer Science
2261    .about.rim.d.credits.f.f.2 configure -text [shuffle_rats "Angela Sasse" "Vicky Hardman" "Peter Kirstein"]
2262    .about.rim.d.credits.f.f.4 configure -text [shuffle_rats "Colin Perkins" "Orion Hodson"]
2263    .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"]
2264}
2265
2266proc sync_ui_to_engine {} {
2267    # the next time the display is shown, it needs to reflect the
2268    # state of the audio engine.
2269    mbus_send "R" "tool.rat.settings" ""
2270}
2271
2272proc sync_engine_to_ui {} {
2273    # make audio engine concur with ui
2274    global my_ssrc rtcp_name rtcp_email rtcp_phone rtcp_loc rtcp_note
2275    global prenc upp channel_var secenc layerenc red_off int_gap int_units
2276    global silence_var agc_var audio_loop_var echo_var
2277    global repair_var limit_var min_var max_var lecture_var 3d_audio_var convert_var 
2278    global meter_var gain volume iport oport
2279    global in_mute_var out_mute_var ichannels freq key key_var
2280    global audio_device received
2281
2282    #rtcp details
2283    mbus_send "R" "rtp.source.name"  "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_name]"
2284    mbus_send "R" "rtp.source.email" "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_email]"
2285    mbus_send "R" "rtp.source.phone" "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_phone]"
2286    mbus_send "R" "rtp.source.loc"   "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_loc]"
2287    mbus_send "R" "rtp.source.note"   "[mbus_encode_str $my_ssrc] [mbus_encode_str $rtcp_note]"
2288
2289    #cheat to update my details right away (it's disgusting)
2290    mbus_recv_rtp.source.name  $my_ssrc "$rtcp_name"
2291    mbus_recv_rtp.source.email $my_ssrc "$rtcp_email"
2292    mbus_recv_rtp.source.phone $my_ssrc "$rtcp_phone"
2293    mbus_recv_rtp.source.loc   $my_ssrc "$rtcp_loc"
2294    mbus_recv_rtp.source.note  $my_ssrc "$rtcp_note"
2295   
2296    #transmission details
2297    mbus_send "R" "tool.rat.codec"      "[mbus_encode_str $prenc] [mbus_encode_str $ichannels] [mbus_encode_str $freq]"
2298    mbus_send "R" "tool.rat.rate"         $upp
2299
2300    switch $channel_var {
2301        none         {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var]"}
2302        redundancy   {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var] [mbus_encode_str $secenc] $red_off"}
2303        interleaved {mbus_send "R" "audio.channel.coding" "[mbus_encode_str $channel_var] $int_gap $int_units"}
2304        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"}
2305        *           {error "unknown channel coding scheme $channel_var"}
2306    }
2307
2308    mbus_send "R" "tool.rat.silence"       $silence_var
2309    mbus_send "R" "tool.rat.agc"           $agc_var
2310    mbus_send "R" "tool.rat.loopback.gain" $audio_loop_var
2311    mbus_send "R" "tool.rat.echo.suppress" $echo_var
2312
2313    #Reception Options
2314    mbus_send "R" "audio.channel.repair"   [mbus_encode_str $repair_var]
2315    mbus_send "R" "tool.rat.playout.limit" $limit_var
2316    mbus_send "R" "tool.rat.playout.min"   $min_var
2317    mbus_send "R" "tool.rat.playout.max"   $max_var
2318    mbus_send "R" "tool.rat.lecture.mode"  $lecture_var
2319    mbus_send "R" "audio.3d.enabled"    $3d_audio_var
2320    mbus_send "R" "tool.rat.converter"     [mbus_encode_str $convert_var]
2321
2322    #Security
2323    if {$key_var==1 && [string length $key]!=0} {
2324        mbus_send "R" "security.encryption.key" [mbus_encode_str $key]
2325    } else {
2326        mbus_send "R" "security.encryption.key" [mbus_encode_str ""]
2327    }
2328
2329    #Interface
2330    mbus_send "R" "tool.rat.powermeter"   $meter_var
2331
2332    #device
2333    mbus_send "R" "audio.device"        [mbus_encode_str "$audio_device"]
2334    if {$received(gain)} {
2335        mbus_send "R" "audio.input.gain"    $gain
2336    }
2337    if {$received(volume)} {
2338        mbus_send "R" "audio.output.gain"   $volume
2339    }
2340    mbus_send "R" "audio.input.port"    [mbus_encode_str $iport]
2341    mbus_send "R" "audio.output.port"   [mbus_encode_str $oport]
2342    mbus_send "R" "audio.input.mute"    $in_mute_var
2343    mbus_send "R" "audio.output.mute"   $out_mute_var
2344}
2345
2346#
2347# Routines to display the "chart" of RTCP RR statistics...
2348#
2349
2350toplevel  .chart
2351canvas    .chart.c  -xscrollcommand {.chart.sb set} -yscrollcommand {.chart.sr set}
2352frame     .chart.c.f
2353scrollbar .chart.sr -orient vertical   -command {.chart.c yview}
2354scrollbar .chart.sb -orient horizontal -command {.chart.c xview}
2355
2356pack .chart.sb -side bottom -fill x    -expand 0 -anchor s
2357pack .chart.sr -side right  -fill y    -expand 0 -anchor e
2358pack .chart.c  -side left   -fill both -expand 1 -anchor n
2359
2360.chart.c create window 0 0 -anchor nw -window .chart.c.f
2361
2362proc mtrace_callback {fd src dst} {
2363        if [winfo exists .mtrace-$src-$dst] {
2364                .mtrace-$src-$dst.t insert end [read $fd]
2365        } else {
2366                # The user has closed the mtrace window before the trace has completed
2367                close $fd
2368        }
2369        if [eof $fd] {
2370                close $fd
2371        }
2372}
2373
2374proc mtrace {src dst} {
2375        global CNAME group_addr
2376        regsub {.*@([0-9]+.[0-9]+.[0-9]+.[0-9]+)} $CNAME($src) {\1} src_addr
2377        regsub {.*@([0-9]+.[0-9]+.[0-9]+.[0-9]+)} $CNAME($dst) {\1} dst_addr
2378
2379        toplevel  .mtrace-$src-$dst
2380        text      .mtrace-$src-$dst.t -background white -font "Courier 8" -wrap none \
2381                                      -yscrollcommand ".mtrace-$src-$dst.sr set" \
2382                                      -xscrollcommand ".mtrace-$src-$dst.sb set"
2383        scrollbar .mtrace-$src-$dst.sb -command ".mtrace-$src-$dst.t xview" -orient horizontal
2384        scrollbar .mtrace-$src-$dst.sr -command ".mtrace-$src-$dst.t yview" -orient vertical
2385        pack .mtrace-$src-$dst.sb -fill x    -expand 0 -side bottom -anchor s
2386        pack .mtrace-$src-$dst.sr -fill y    -expand 0 -side right  -anchor e
2387        pack .mtrace-$src-$dst.t  -fill both -expand 1 -side left   -anchor w
2388
2389        wm title .mtrace-$src-$dst "mtrace from $src_addr to $dst_addr via group $group_addr"
2390
2391        set fd [open "|mtrace $src_addr $dst_addr $group_addr" "r"]
2392        fconfigure $fd -blocking 0
2393        fileevent  $fd readable "mtrace_callback $fd $src $dst"
2394}
2395
2396toplevel .chart_popup       -bg black
2397label    .chart_popup.text  -bg lavender -justify left
2398pack .chart_popup.text -side top -anchor w -fill x
2399wm transient        .chart_popup .
2400wm withdraw         .chart_popup
2401wm overrideredirect .chart_popup true
2402
2403proc chart_popup_show {window} {
2404        global chart_popup_src chart_popup_dst chart_popup_id NAME
2405        .chart_popup.text  configure -text "From: $NAME($chart_popup_src($window))\nTo: $NAME($chart_popup_dst($window))"
2406        # Beware! Don't put the popup under the cursor! Else we get window enter
2407        # for .help and leave for $window, making us hide_help which removes the
2408        # help window, giving us a window enter for $window making us popup the
2409        # help again.....
2410        if {[winfo width $window] > [winfo height $window]} {
2411            set xpos [expr [winfo pointerx $window] + 10]
2412            set ypos [expr [winfo rooty    $window] + [winfo height $window] + 4]
2413        } else {
2414            set xpos [expr [winfo rootx    $window] + [winfo width $window] + 4]
2415            set ypos [expr [winfo pointery $window] + 10]
2416        }
2417       
2418        wm geometry  .chart_popup +$xpos+$ypos
2419        set chart_popup_id [after 100 wm deiconify .chart_popup]
2420        raise .chart_popup $window
2421}
2422
2423proc chart_popup_hide {window} {
2424        global chart_popup_id
2425        if {[info exists chart_popup_id]} {
2426                after cancel $chart_popup_id
2427        }
2428        wm withdraw .chart_popup
2429}
2430
2431proc chart_popup_add {window src dst} {
2432        global chart_popup_src chart_popup_dst
2433        set chart_popup_src($window) $src
2434        set chart_popup_dst($window) $dst
2435        bind $window <Enter>    "+chart_popup_show $window"
2436        bind $window <Leave>    "+chart_popup_hide $window"
2437}
2438
2439proc chart_add {ssrc} {
2440        global NAME
2441        frame  .chart.c.f.$ssrc
2442        frame  .chart.c.f.$ssrc.f
2443        button .chart.c.f.$ssrc.l -width 25 -text $ssrc -padx 0 -pady 0 -anchor w -relief flat -command "toggle_stats $ssrc"
2444        pack   .chart.c.f.$ssrc.f -expand 0 -anchor e -side right
2445        pack   .chart.c.f.$ssrc.l -expand 1 -anchor w -fill x -side left
2446        pack   .chart.c.f.$ssrc   -expand 1 -anchor n -fill x -side top
2447        foreach s [pack slaves .chart.c.f] {
2448                regsub {.chart.c.f.(.*)} $s {\1} s
2449                button .chart.c.f.$s.f.$ssrc -width 4 -text "" -background white -padx 0 -pady 0 -command "mtrace $s $ssrc"
2450                pack   .chart.c.f.$s.f.$ssrc -expand 0 -side left
2451                chart_popup_add .chart.c.f.$s.f.$ssrc $s $ssrc
2452                if {![winfo exists .chart.c.f.$ssrc.f.$s]} {
2453                        button .chart.c.f.$ssrc.f.$s -width 4 -text "" -background white -padx 0 -pady 0 -command "mtrace $ssrc $s"
2454                        pack   .chart.c.f.$ssrc.f.$s -expand 0 -side left
2455                        chart_popup_add .chart.c.f.$ssrc.f.$s $ssrc $s
2456                }
2457        }
2458        update
2459        .chart.c configure -scrollregion "0.0 0.0 [winfo width .chart.c.f] [winfo height .chart.c.f]"
2460}
2461
2462proc chart_remove {ssrc} {
2463        destroy .chart.c.f.$ssrc
2464        foreach s [pack slaves .chart.c.f] {
2465                regsub {.chart.c.f.(.*)} $s {\1} s
2466                destroy .chart.c.f.$s.f.$ssrc
2467        }
2468        update
2469        .chart.c configure -scrollregion "0.0 0.0 [winfo width .chart.c.f] [winfo height .chart.c.f]"
2470}
2471
2472proc chart_label {ssrc label} {
2473        .chart.c.f.$ssrc.l configure -text $label
2474}
2475
2476proc chart_set {src dst val} {
2477        if {$val < 5} {
2478                set colour green
2479                set txtval "$val%"
2480        } elseif {$val < 10} {
2481                set colour orange
2482                set txtval "$val%"
2483        } elseif {$val <= 100} {
2484                set colour red
2485                set txtval "$val%"
2486        } else {
2487                set colour white
2488                set txtval { }
2489        }
2490        .chart.c.f.$src.f.$dst configure -background $colour -text "$txtval"
2491}
2492
2493proc chart_show {} {
2494        global matrix_on
2495        if {$matrix_on} {
2496                wm deiconify .chart
2497        } else {
2498                wm withdraw .chart
2499        }
2500}
2501
2502wm withdraw .chart
2503wm title    .chart "Reception quality matrix"
2504wm geometry .chart 320x200
2505wm protocol .chart WM_DELETE_WINDOW    {set matrix_on 0; chart_show}
2506
2507chart_show
2508
2509#
2510# End of RTCP RR chart routines
2511#
2512
2513#
2514# File Control Window
2515#
2516
2517set play_file(state) end
2518set rec_file(state) end
2519
2520catch {
2521    toplevel .file
2522    frame .file.play -relief groove -bd 2
2523    frame .file.rec  -relief groove -bd 2
2524    pack  .file.play -side top -pady 2 -padx 2 -fill x -expand 1
2525    pack  .file.rec  -side top -pady 2 -padx 2 -fill x -expand 1
2526   
2527    label .file.play.l -text "Playback"
2528    pack  .file.play.l -side top -fill x
2529    label .file.rec.l -text "Record"   
2530    pack  .file.rec.l -side top -fill x
2531
2532    wm withdraw .file
2533    wm title    .file "RAT File Control"
2534    wm protocol .file WM_DELETE_WINDOW "set files_on 0; file_show"
2535   
2536    foreach action { play rec } {
2537        frame  .file.$action.buttons
2538        pack   .file.$action.buttons
2539        button .file.$action.buttons.disk -bitmap disk -command "fileDialog $action"
2540        pack   .file.$action.buttons.disk -side left -padx 2 -pady 2 -anchor n
2541       
2542        foreach cmd "$action pause stop" {
2543            button .file.$action.buttons.$cmd -bitmap $cmd -state disabled -command file_$action\_$cmd
2544            pack   .file.$action.buttons.$cmd -side left -padx 2 -pady 2 -anchor n -fill x
2545        }
2546
2547        label  .file.$action.buttons.status -text "No file selected." -width 16 -anchor w
2548        pack   .file.$action.buttons.status -side bottom -fill both -expand 1 -padx 2 -pady 2
2549    }
2550} fwinerr
2551
2552if {$fwinerr != {}} {
2553        puts stderr $fwinerr
2554}
2555
2556proc fileDialog {cmdbox} {
2557    global win32 tcl_platform
2558   
2559        set defaultExtension au
2560        set defaultLocation  .
2561
2562    switch -glob $tcl_platform(os) {
2563        SunOS    {
2564                if [file exists /usr/demo/SOUND/sounds] { set defaultLocation /usr/demo/SOUND/sounds }
2565                }
2566        Windows* {
2567                if [file exists C:/Windows/Media]       { set defaultLocation C:/Windows/Media }
2568                set defaultExtension wav
2569                }
2570        }
2571   
2572    set types {
2573                {"NeXT/Sun Audio files" "au"}
2574                {"Microsoft RIFF files" "wav"}
2575                {"All files"            "*"}
2576    }
2577   
2578    if {![string compare $cmdbox "play"]} {
2579                catch { asFileBox .playfilebox  -defaultextension $defaultExtension -command file_open_$cmdbox -directory $defaultLocation -extensions $types } asferror
2580    } else {
2581                catch { asFileBox .recfilebox   -defaultextension $defaultExtension -command file_open_$cmdbox  -extensions $types -force_extension 1 } asferror
2582    }
2583       
2584        if {$asferror != ""} {
2585                puts stderr asferror
2586        }
2587}
2588
2589proc file_show {} {
2590    global files_on
2591   
2592    if {$files_on} {
2593                wm deiconify .file
2594    } else {
2595                wm withdraw .file
2596    }
2597}
2598
2599proc file_play_live {} {
2600# Request heart beat to determine if file is valid
2601        mbus_send "R" audio.file.play.live ""
2602}
2603
2604proc file_rec_live {} {
2605# Request heart beat to determine if file is valid
2606        mbus_send "R" audio.file.record.live ""
2607}
2608
2609proc file_open_play {path} {
2610    global play_file
2611
2612    mbus_send "R" "audio.file.play.open" [mbus_encode_str $path]
2613    mbus_send "R" "audio.file.play.pause" 1
2614    set play_file(state) paused
2615    set play_file(name) $path
2616   
2617    # Test whether file is still playing/valid
2618    after 200 file_play_live
2619}
2620
2621proc file_open_rec {path} {
2622    global rec_file
2623
2624    mbus_send "R" "audio.file.record.open" [mbus_encode_str $path]
2625    mbus_send "R" "audio.file.record.pause" 1
2626
2627    set rec_file(state) paused
2628    set rec_file(name)  $path
2629
2630    # Test whether file is still recording/valid
2631    after 200 file_rec_live
2632}
2633
2634proc file_enable_play { } {
2635    .file.play.buttons.play   configure -state normal
2636    .file.play.buttons.pause  configure -state disabled
2637    .file.play.buttons.stop   configure -state disabled
2638    .file.play.buttons.status configure -text "Ready to play."
2639}       
2640
2641proc file_enable_record { } {
2642    .file.rec.buttons.rec configure -state normal
2643    .file.rec.buttons.pause  configure -state disabled
2644    .file.rec.buttons.stop   configure -state disabled
2645    .file.rec.buttons.status configure -text "Ready to record."
2646}
2647
2648proc file_play_play {} {
2649        global play_file
2650       
2651        catch {
2652                if {$play_file(state) == "paused"} {
2653                        mbus_send "R" "audio.file.play.pause" 0
2654                } else {
2655                        mbus_send "R" "audio.file.play.open" [mbus_encode_str $play_file(name)]
2656                }
2657                set play_file(state) play
2658        } pferr
2659
2660        if { $pferr != "play" } { puts stderr "pferr: $pferr" }
2661
2662        .file.play.buttons.play   configure -state disabled
2663        .file.play.buttons.pause  configure -state normal
2664        .file.play.buttons.stop   configure -state normal
2665        .file.play.buttons.status configure -text "Playing."
2666        after 200 file_play_live
2667}
2668
2669proc file_play_pause {} {
2670    global play_file
2671   
2672    .file.play.buttons.play   configure -state normal
2673    .file.play.buttons.pause  configure -state disabled
2674    .file.play.buttons.stop   configure -state normal
2675    .file.play.buttons.status configure -text "Paused."
2676    set play_file(state) paused
2677    mbus_send "R" "audio.file.play.pause" 1
2678}
2679
2680proc file_play_stop {} {
2681        global play_file
2682       
2683        set play_file(state) end
2684        file_enable_play
2685        mbus_send "R" "audio.file.play.stop" ""
2686}
2687
2688proc file_rec_rec {} {
2689        global rec_file
2690       
2691        catch {
2692                if {$rec_file(state) == "paused"} {
2693                        mbus_send "R" "audio.file.record.pause" 0
2694                } else {
2695                        mbus_send "R" "audio.file.record.open" [mbus_encode_str $rec_file(name)]
2696                }
2697                set rec_file(state) record
2698        } prerr
2699
2700        if { $prerr != "record" } { puts stderr "prerr: $prerr" }
2701
2702        .file.rec.buttons.rec    configure -state disabled
2703        .file.rec.buttons.pause  configure -state normal
2704        .file.rec.buttons.stop   configure -state normal
2705        .file.rec.buttons.status configure -text "Recording."
2706        after 200 file_rec_live
2707}
2708
2709proc file_rec_pause {} {
2710    global rec_file
2711   
2712    .file.rec.buttons.rec    configure -state normal
2713    .file.rec.buttons.pause  configure -state disabled
2714    .file.rec.buttons.stop   configure -state normal
2715    .file.rec.buttons.status configure -text "Paused."
2716    set rec_file(state) paused
2717    mbus_send "R" "audio.file.record.pause" 1
2718}
2719
2720proc file_rec_stop {} {
2721        global rec_file
2722       
2723        set rec_file(state) end
2724        file_enable_record
2725        mbus_send "R" "audio.file.record.stop" ""
2726}
2727
2728#
2729# End of File Window routines
2730#
2731
2732proc show_help {window} {
2733        global help_text help_on help_id help_clip
2734        if {$help_on} {
2735                .help.text  configure -text $help_text($window)
2736                # Beware! Don't put the popup under the cursor! Else we get window enter
2737                # for .help and leave for $window, making us hide_help which removes the
2738                # help window, giving us a window enter for $window making us popup the
2739                # help again.....
2740                if {[winfo width $window] > [winfo height $window]} {
2741                    set xpos [expr [winfo pointerx $window] + 10]
2742                    set ypos [expr [winfo rooty    $window] + [winfo height $window] + 4]
2743                } else {
2744                    set xpos [expr [winfo rootx    $window] + [winfo width $window] + 4]
2745                    set ypos [expr [winfo pointery $window] + 10]
2746                }
2747               
2748                wm geometry  .help +$xpos+$ypos
2749                set help_id [after 100 wm deiconify .help]
2750                raise .help $window
2751                if {[info exists help_clip($window)]} {
2752                    mbus_send "R" "tool.rat.voxlet.play" "\"$help_clip($window)\""
2753                }
2754        }
2755}
2756
2757proc hide_help {window} {
2758        global help_id help_on
2759        if {[info exists help_id]} {
2760                after cancel $help_id
2761        }
2762        wm withdraw .help
2763}
2764
2765proc add_help {window text clip} {
2766        global help_text help_clip
2767        set help_text($window)  $text
2768        set help_clip($window)  $clip
2769        bind $window <Enter>    "+show_help $window"
2770        bind $window <Leave>    "+hide_help $window"
2771}
2772
2773bind Entry   <KeyPress> "+hide_help %W"
2774toplevel .help       -bg black
2775label    .help.text  -bg lavender -justify left
2776pack .help.text -side top -anchor w -fill x
2777wm transient        .help .
2778wm withdraw         .help
2779wm overrideredirect .help true
2780
2781add_help .r.c.tx.au.pow.sli     "This slider controls the volume\nof the sound you send." "tx_gain.au"
2782add_help .r.c.tx.au.port.l0     "Click to change input device." "tx_port.au"
2783add_help .r.c.tx.au.port.l2     "Click to change input device." "tx_port.au"
2784add_help .r.c.tx.net.on         "If this button is pushed in, you are are transmitting, and\nmay be\
2785                                 heard by other participants. Holding down the\nright mouse button in\
2786                                 any RAT window will temporarily\ntoggle the state of this button,\
2787                                 allowing for easy\npush-to-talk operation." "tx_mute.au"
2788add_help .r.c.tx.au.pow.bar     "Indicates the loudness of the\nsound you are sending. If this\nis\
2789                                 moving, you may be heard by\nthe other participants." "tx_powermeter.au"
2790
2791add_help .r.c.rx.au.pow.sli     "This slider controls the volume\nof the sound you hear." "rx_gain.au"
2792add_help .r.c.rx.au.port.l0     "Click to change output device." "rx_port.au"
2793add_help .r.c.rx.au.port.l2     "Click to change output device." "rx_port.au"
2794add_help .r.c.rx.net.on         "If pushed in, reception is muted." "rx_mute.au"
2795add_help .r.c.rx.au.pow.bar     "Indicates the loudness of the\nsound you are hearing." "rx_powermeter.au"
2796
2797add_help .l.f           "Name of the session, and the IP address, port\n&\
2798                         TTL used to transmit the audio data." "session_title.au"
2799add_help .l.t           "The participants in this session with you at the top.\nClick on a name\
2800                         with the left mouse button to display\ninformation on that participant,\
2801                         and with the middle\nbutton to mute that participant (the right button\nwill\
2802                         toggle the transmission mute button, as usual)." "participant_list.au"
2803
2804add_help .st.help       "If you can see this, balloon help\nis enabled. If not, it isn't." "balloon_help.au"
2805add_help .st.opts       "Brings up another window allowing\nthe control of various options." "options.au"
2806add_help .st.about      "Brings up another window displaying\ncopyright & author information." "about.au"
2807add_help .st.quit       "Press to leave the session." "quit.au"
2808
2809# preferences help
2810add_help .prefs.m.f.m  "Click here to change the preference\ncategory." "prefs_category.au"
2811set i .prefs.buttons
2812add_help $i.bye         "Cancel changes." "cancel_changes.au"
2813add_help $i.apply       "Apply changes." "apply_changes.au"
2814
2815# user help
2816set i .prefs.pane.personal.a.f.f.ents
2817add_help $i.name        "Enter your name for transmission\nto other participants." "user_name.au"
2818add_help $i.email       "Enter your email address for transmission\nto other participants." "user_email.au"
2819add_help $i.phone       "Enter your phone number for transmission\nto other participants." "user_phone.au"
2820add_help $i.loc         "Enter your location for transmission\nto other participants." "user_loc.au"
2821
2822#audio help
2823set i .prefs.pane.audio
2824add_help $i.dd.device.mdev "Selects preferred audio device." "audio_device.au"
2825add_help $i.dd.sampling.freq.mb \
2826                        "Sets the sampling rate of the audio device.\nThis changes the available codecs." "sampling_freq.au"
2827add_help $i.dd.sampling.ch_in.mb \
2828                        "Changes between mono and stereo audio input." "mono_stereo.au"
2829add_help $i.dd.cks.f.f.silence\
2830                         "Prevents silence from being transmitted when the speaker is silent\n\
2831                          and the input is unmuted." "suppress_silence.au"
2832add_help $i.dd.cks.f.f.agc       "Enables automatic control of the volume\nof the sound you send." "agc.au"
2833add_help $i.dd.cks.f.f.loop "Enables hardware for loopback of audio input." "audio_loopback.au"
2834add_help $i.dd.cks.f.f.suppress \
2835                         "Mutes microphone when playing audio." "echo_suppression.au"
2836
2837# transmission help
2838set i .prefs.pane.transmission
2839
2840add_help $i.dd.units.m  "Sets the duration of each packet sent.\nThere is a fixed per-packet\
2841                         overhead, so\nmaking this larger will reduce the total\noverhead.\
2842                         The effects of packet loss are\nmore noticable with large packets." "packet_duration.au"
2843add_help $i.dd.pri.m    "Changes the primary audio compression\nscheme. The list is arranged\
2844                         with high-\nquality, high-bandwidth choices at the\ntop, and\
2845                         poor-quality, lower-bandwidth\nchoices at the bottom." "codec_primary.au"
2846add_help $i.cc.van.rb   "Sets no channel coding." "channel_coding_none.au"
2847add_help $i.cc.red.rb   "Piggybacks earlier units of audio into packets\n\
2848                         to protect against packet loss. Some audio\n\
2849                         tools (eg: vat-4.0) are not able to receive\n\
2850                         audio sent with this option." "channel_coding_redundant.au"
2851add_help $i.cc.red.fc.m \
2852                        "Sets the format of the piggybacked data." "red_codec.au"
2853add_help $i.cc.red.u.m \
2854                        "Sets the offset of the piggybacked data." "red_offset.au"
2855add_help $i.cc.layer.fc.m  "Sets the number of discrete layers which will\nbe sent. You need\
2856                            to start RAT with the options\n-l n <address>/<port> <address>/<port>,\nwhere\
2857                            n is the number of layers and there is an\naddress and port for each layer.\
2858                            NB: this is only\nsupported by the WBS codec at present." "num_layers.au"
2859add_help $i.cc.int.fc.m \
2860                        "Sets the separation of adjacent units within\neach packet. Larger values correspond\
2861                         to longer\ndelays." "int_sep.au"
2862add_help $i.cc.int.zz.m "Number of compound units per packet." "int_units.au"
2863add_help $i.cc.int.rb   "Enables interleaving which exchanges latency\n\
2864                         for protection against burst losses.  No other\n\
2865                         audio tools can decode this format (experimental)." "channel_coding_interleave.au"
2866
2867# Reception Help
2868set i .prefs.pane.reception
2869add_help $i.r.m         "Sets the type of repair applied when packets are\nlost. The schemes\
2870                         are listed in order of increasing\ncomplexity and quality of repair." "repair_schemes.au"
2871add_help $i.r.ms        "Sets the type of sample rate conversion algorithm\n\
2872                         that will be applied to streams that differ in rate\n\
2873                         to the audio device rate." "samples_rate_conversion.au"
2874add_help $i.o.f.cb      "Enforce playout delay limits set below.\nThis is not usually desirable." "playout_limits.au"
2875add_help $i.o.f.fl.scmin   "Sets the minimum playout delay that will be\napplied to incoming\
2876                         audio streams." "min_playout_delay.au"
2877add_help $i.o.f.fr.scmax   "Sets the maximum playout delay that will be\napplied to incoming\
2878                         audio streams." "max_playout_delay.au"
2879add_help $i.c.f.f.lec   "If enabled, extra delay is added at both sender and receiver.\nThis allows\
2880                         the receiver to better cope with host scheduling\nproblems, and the sender\
2881                         to perform better silence suppression.\nAs the name suggests, this option\
2882                         is intended for scenarios such\nas transmitting a lecture, where interactivity\
2883                         is less important\nthan quality." "lecture_mode.au"
2884
2885# security...too obvious for balloon help!
2886add_help .prefs.pane.security.a.f.f.e "Due to government export restrictions\nhelp\
2887                                       for this option is not available." "security.au"
2888
2889# interface...ditto!
2890set i .prefs.pane.interface
2891add_help $i.a.f.f.power "Disable display of audio powermeters. This\nis only\
2892                         useful if you have a slow machine" "disable_powermeters.au"
2893add_help $i.a.f.f.balloon "If you can see this, balloon help\nis enabled. If not, it isn't." "balloon_help.au"
2894add_help $i.a.f.f.matrix  "Displays a chart showing the reception\nquality reported by all participants" "rqm_enable.au"
2895add_help $i.a.f.f.plist   "Hides the list of participants" "participant_list.au"
2896
2897add_help .chart         "This chart displays the reception quality reported\n by all session\
2898                         participants. Looking along a row\n gives the quality with which that\
2899                         participant was\n received by all other participants in the session:\n green\
2900                         is good quality, orange medium quality, and\n red poor quality audio." "rqm.au"
2901
2902
2903} script_error
2904
2905if { $script_error != "" } {
2906    puts "Error: \"$script_error\""
2907    destroy .
2908    exit -1
2909}
2910
2911proc rendezvous_with_media_engine {} {
2912        mbus_send "R" "tool.rat.settings" ""
2913        mbus_send "R" "audio.query" ""
2914        mbus_send "R" "rtp.query" ""
2915}
Note: See TracBrowser for help on using the browser.