1 # ui-client.tcl --
2 #
3 # FIXME: This file needs a description here.
4 #
5 # Copyright (c) 1996-2002 The Regents of the University of California.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # A. Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # B. Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # C. Neither the names of the copyright holders nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #
31 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/rvic-client/ui-client.tcl,v 1.20 2002/02/03 04:29:33 lim Exp $
32
33
34 #
35 # client for rvic
36 #
37 Class RvicClientUI
38
39
40 #
41 # constuctor takes <br>
42 # `w', a window to build itself in, and <br>
43 # `ctrladdrSpec', the address spec of the server to talk to.
44 #
45 RvicClientUI public init {w ctrladdrspec} {
46 $self instvar al_ layouts_
47
48 set origAddr $ctrladdrspec
49
50 # if addrspec includes a name, turn it into IP addr
51 set firstchar [string index $ctrladdrspec 0]
52 if [string match \[a-zA-Z\] $firstchar] {
53 set n [lindex [split $ctrladdrspec "/"] 0]
54 set p [lindex [split $ctrladdrspec "/"] 1]
55 set s [gethostbyname $n]
56 if { $s == "" } {
57 puts "cannot find address for '$n'..."
58 return -1
59 }
60 set ctrladdrspec $s/$p
61 }
62
63 # create rvic's announce-listen manager object
64 set al_ [new ALM/RvicClient $ctrladdrspec $self]
65
66 # initialize with one layout -- 'Single' 1 full-screen vw
67 set layouts_(Single) "1.0x1.0+0.0+0.0"
68
69 $self build_gui $w $origAddr
70 }
71
72 #
73 RvicClientUI public destroy {} {
74 $self instvar al_
75 $al_ destroy
76 eval [list $self] next
77 }
78
79 #
80 # builds the client gui in windows `w'. `subtitle' is a
81 # string appended to the informational bottom label, ie,
82 # the address/port of the rvic server it is connected to.
83 #
84 RvicClientUI private build_gui {w subtitle} {
85 $self instvar al_ status_ w_ numSrcs_ \
86 currSrc_ numVWs_ layout_switching_ addrspec_
87 set w_ $w
88 set numSrcs_ 0
89 set currSrc_ ""
90 set numVWs_ 0
91 set layout_switching_ off
92
93 # build bottom informational label
94 set il $w.infolabel
95 frame $il -relief groove
96 label $il.l -text "rvic client for $subtitle"
97 pack $il -side bottom -fill x -expand 1
98 pack $il.l -in $il -side bottom
99
100 # build frame for buttons representing video-windows
101 frame $w.vws -width 320 -height 240 -relief groove
102 pack $w.vws -side left
103
104 # build middle src list panel
105 frame $w.srcs -relief groove
106 label $w.srcs.l -text "Sources:" -anchor w
107 pack $w.srcs -side bottom
108 pack $w.srcs.l -side top -fill x -expand 1
109
110 # build layouts, switching. update, ... buttons/menubuttons
111 set m $w.layouts.menu
112 menubutton $w.layouts -text Layouts... -menu $m -relief raised
113 menu $m -tearoff 0
114 $m add command -label Single -command "$self set_layout Single"
115 pack $w.layouts -side top -expand 1 -fill x
116
117 button $w.refresh -text "Refresh" -command "$al_ request_full_update"
118 pack $w.refresh -side top -expand 1 -fill x
119
120 # the address label and switch button
121 #frame $w.address
122 #label $w.address.info -anchor w -text "Session: "
123 #set addrspec_ $w.address.info
124
125 #button $w.address.switch -text "Switch Address"\
126 # -command "$al_ switch_address 224.1.2.3/12345"
127 #pack $w.address.info $w.address.switch -side top -fill x -expand 1
128 #pack $w.address -side top -expand 1 -fill x
129
130 #
131 checkbutton $w.match -text "Match layout to \# srcs" \
132 -variable [$self tkvarname match_srcs_button_state] \
133 -command "$self invoke_match_srcs_button"
134 pack $w.match -side top -expand 1 -fill x ; # -anchor w
135
136 set m $w.vswitch.menu
137 menubutton $w.vswitch -text "Voice Switch..." -menu $m -relief raised
138 menu $m -tearoff 0
139 foreach ii {1 2 3 4 5 6 7 8 9} {
140 $m add checkbutton -label "Voice-switch $ii" \
141 -command "$self toggle_voice_switch $ii"
142 }
143 pack $w.vswitch -side right -expand 1
144
145 set m $w.tswitch.menu
146 menubutton $w.tswitch -text "Timer Switch..." -menu $m -relief raised
147 menu $m -tearoff 0
148 foreach ii {1 2 3 4 5 6 7 8 9} {
149 $m add checkbutton -label "Timer-switch $ii" -command \
150 "$self toggle_timer_switch $ii"
151 }
152 pack $w.tswitch -side left -expand 1
153
154 bind . <q> exit
155 bind . <n> {}
156
157 # setup timeout rate; request current state,
158 # then start occasional re-querying
159 set t [new Timer/Periodic 5000]
160 $t randomize 1
161 $al_ timer $t
162 $al_ request_full_update
163 $al_ start
164 }
165
166
167 # set local layout and then send update to the server
168 #
169 RvicClientUI public set_layout {layout} {
170 $self instvar al_ currLayout_
171 $self set_local_layout $layout
172 $al_ announce "Set MonitorStyle $currLayout_"
173 # grab vw-->cname mappings
174 $al_ announce "Set VideoWindow"
175 }
176
177
178 # set current "layout" of buttons representing vwins to name in
179 # param 'layout'
180 #
181 RvicClientUI public set_local_layout {layout} {
182 $self instvar layouts_ currLayout_
183
184 set i [lsearch [array get layouts_] $layout]
185 if {$i == -1} {
186 puts "Bad layout name: $layout"
187 return
188 }
189 set currLayout_ $layout
190 $self update_layout $layouts_($currLayout_)
191 }
192
193 # move to "next" layout in the layout list and announce the change to
194 # the server
195 #
196 RvicClientUI public next_layout {} {
197 $self instvar layouts_ currLayout_ al_
198
199 if {![info exists currLayout_]} {
200 set index 0
201 } else {
202 set l [array get layouts_]
203 set index [lsearch $l $currLayout_]
204 incr index 2
205 if {$index >= [llength $l]} {
206 set index 0
207 }
208 }
209 set currLayout_ [lindex [array get layouts_] $index]
210 #puts "currLayout = $currLayout_"
211 $self update_layout $layouts_($currLayout_)
212 $al_ announce "Set MonitorStyle $currLayout_"
213 }
214
215
216 #
217 # update the list of possible "layouts" of the buttons representing
218 # remote video windows. `layoutsList' is expected to be a list
219 # of the form:<br>
220 # layoutName {WxH+X+Y [WxH+X+Y ...] } <br>
221 # layoutName2 {WxH+X+Y [WxH+X+Y ...] } <br>
222 # ...
223 #
224 RvicClientUI private update_layouts_list {layoutList} {
225 $self instvar w_ layouts_ currLayout_
226
227 $w_.layouts.menu delete 0 end
228 foreach {name values} $layoutList {
229 set layouts_($name) "$values"
230 #puts "- $name -=- $values -"
231 $w_.layouts.menu add command -label $name \
232 -command "$self set_layout $name"
233 }
234 # if first update, set to first layout
235 if {![info exists currLayout_]} {
236 $self set_local_layout "[lindex $layoutList 0]"
237 #puts "setting layout to [lindex $layoutList 0]"
238 }
239 }
240
241
242 #
243 # update radio buttons src list to the strings in list srcNamesList
244 # <br> updates the numSrcs_ and currSrc_ instvars to match
245 #
246 RvicClientUI private update_src_list {srcNamesList} {
247 $self instvar w_ numSrcs_ currSrc_
248
249 set s $srcNamesList
250 set fr $w_.srcs
251 set newLen [llength $s]
252 if {$srcNamesList == ""} {set newLen 0}
253
254 # add/delete buttons to match number of srcs
255 if {$numSrcs_ < $newLen} {
256 for {set i [expr $numSrcs_+1]} {$i <= $newLen} {incr i} {
257 radiobutton $fr.rb$i -variable srcs -value $i
258 }
259 } elseif {$numSrcs_ > $newLen} {
260 for {set i [expr $newLen+1]} {$i <= $numSrcs_} {incr i} {
261 destroy $fr.rb$i
262 }
263 }
264 set numSrcs_ $newLen
265
266 # update contents and pack 'em
267 for {set i 1} {$i <= $numSrcs_} {incr i} {
268 set l [lindex $s [expr $i-1]]
269 $fr.rb$i configure -text "$l" \
270 -command "$self set currSrc_ \"$l\""
271 pack $fr.rb$i -in $fr -side top -anchor w -padx 4
272 }
273
274 if {[info exists currSrc_]} {
275 set i [lsearch -exact $srcNamesList $currSrc_]
276 } else {
277 set i -1
278 }
279 if {$i != -1} {
280 set currSrc_ [lindex $s $i]
281 $fr.rb[expr $i+1] select
282 } else {
283 set currSrc_ [lindex $s 0]
284 if {[info commands $fr.rb1] != ""} {$fr.rb1 select}
285 }
286 }
287
288
289 #
290 # updates the src address label
291 #
292 RvicClientUI private update_src_address {address} {
293 $self instvar w_ numSrcs_ currSrc_
294 $self instvar addrspec_
295
296 if ![info exists addrspec_] {
297 return
298 }
299 $addrspec_ configure -text "Session: $address"
300 }
301
302
303 #
304 # update buttons representing video windows (a "layout") to list of
305 # 4-tuples passed in that each represent a button. 4-tuples include
306 # relative position in 0.0..1.0 (-xrel, -yrel) of frame representing
307 # the remote "full screen" and the height and width of the individual
308 # button, again each relative in 0.0..1.0 <br>
309 # ... thus, tuple = `HxW+X+Y', like a geometry string
310 #
311 RvicClientUI private update_layout {tupleList} {
312 $self instvar numVWs_ w_
313
314 #puts "update to tupleList: $tupleList"
315
316 set t $tupleList
317 set newLen [llength $t]
318 set fr $w_.vws
319
320 # add/delete buttons to match number of srcs
321 if {$numVWs_ < $newLen} {
322 for {set i [expr $numVWs_+1]} {$i <= $newLen} {incr i} {
323 button $fr.b$i -command "$self hit_layout_button $i" -text $i
324 }
325 } elseif {$numVWs_ > $newLen} {
326 for {set i [expr $newLen+1]} {$i <= $numVWs_} {incr i} {
327 destroy $fr.b$i
328 }
329 }
330 set numVWs_ $newLen
331
332 # update size and place 'em
333 for {set i 1} {$i <= $numVWs_} {incr i} {
334 set geomList [split [lindex $tupleList [expr $i-1]] "+x"]
335 foreach {w h x y} $geomList {
336 place configure $fr.b$i \
337 -relx $x -rely $y -relwidth $w -relheight $h
338 }
339 }
340 }
341
342 #
343 # user hits on layout button: sends message asking that the currently
344 # selected source (the radiobutton) be used as the new source for
345 # the video-window corresponding to the button.
346 #
347 RvicClientUI private hit_layout_button {num} {
348 $self instvar currSrc_ al_
349
350 $al_ announce "Set VideoWindow\n$num $currSrc_"
351 $self set_button_label $num $currSrc_
352 }
353
354 #
355 # make button `num' have label `label'
356 #
357 RvicClientUI private set_button_label {num label} {
358 $self instvar w_
359 if {[string length $label] > 8} {
360 set label "[string range $label 0 7]..."
361 }
362 if {[info commands $w_.vws.b$num] != ""} {
363 $w_.vws.b$num configure -text "$label"
364 }
365 }
366
367 # called when user toggles the "match layout to # srcs" button
368 RvicClientUI private invoke_match_srcs_button {} {
369 $self instvar al_ layout_switching_
370 $self tkvar match_srcs_button_state
371 if $match_srcs_button_state {
372 set state on
373 } else {
374 set state off
375 }
376 $al_ announce "Set Autoswitchlayout $state"
377 set layout_switching_ $state
378 }
379
380
381 # either get the value of the layout_switching_ variable, or
382 # set the layout_switching_ variable by updating the
383 # "match layout to # srcs" checkbutton to match
384 RvicClientUI public set_layout_switching {{onoff ""}} {
385 $self instvar layout_switching_ w_
386 if {$onoff == ""} {
387 return $layout_switching_
388 } else {
389 if {$layout_switching_ != $onoff} {
390 $w_.match invoke
391 }
392 }
393 if {$layout_switching_ != "on" && $layout_switching_ != "off"} {
394 puts "Error: bad arg to set_layout_switching: $onoff"
395 }
396 }
397
398 #
399 RvicClientUI private toggle_timer_switch {num} {
400 $self instvar timer_onoff_ al_ no_announce_
401 if {![info exists timer_onoff_($num)] || $timer_onoff_($num) == 0} {
402 set timer_onoff_($num) 1
403 set r "Set TimerSwitchList\n$num *"
404 } else {
405 set timer_onoff_($num) 0
406 set r "Set TimerSwitchList\n$num"
407 }
408 if ![info exists no_announce_] {
409 $al_ announce $r
410 }
411 }
412
413 #
414 RvicClientUI private toggle_voice_switch {num} {
415 $self instvar voice_onoff_ al_ no_announce_
416 if {![info exists voice_onoff_($num)] || $voice_onoff_($num) == 0} {
417 set voice_onoff_($num) 1
418 set r "Set VoiceSwitchList\n$num *"
419 } else {
420 set voice_onoff_($num) 0
421 set r "Set VoiceSwitchList\n$num"
422 }
423 if ![info exists no_announce_] {
424 $al_ announce $r
425 }
426 }
427
428 #
429 RvicClientUI public update_vs_checkbuttons {data} {
430 $self instvar w_ voice_onoff_ no_announce_
431 set no_announce_ 1
432 # turn 'em all off
433 foreach num {1 2 3 4 5 6 7 8 9} {
434 if {[info exists voice_onoff_($num)] && $voice_onoff_($num) == 1} {
435 $w_.vswitch.menu invoke [expr $num-1]
436 }
437 }
438 # then turn on the notated ones
439 set data [split $data "\n"]
440 set data [lrange $data 1 end]
441 foreach i $data {
442 if {$i == ""} {continue}
443 set num [lindex $i 0]
444 $w_.vswitch.menu invoke [expr $num-1]
445 }
446 unset no_announce_
447 }
448
449 #
450 RvicClientUI public update_ts_checkbuttons {data} {
451 $self instvar w_ timer_onoff_ no_announce_
452 set no_announce_ 1
453 # turn 'em all off
454 foreach num {1 2 3 4 5 6 7 8 9} {
455 if {[info exists timer_onoff_($num)] && $timer_onoff_($num) == 1} {
456 $w_.tswitch.menu invoke [expr $num-1]
457 }
458 }
459 # then turn on the notated ones
460 set data [split $data "\n"]
461 set data [lrange $data 1 end]
462 foreach i $data {
463 if {$i == ""} {continue}
464 set num [lindex $i 0]
465 $w_.tswitch.menu invoke [expr $num-1]
466 }
467 unset no_announce_
468 }
469
470 # ---- # ---- # ---- # ---- # ---- # ---- # ---- # ----
471 # ---- # ---- # ---- # ---- # ---- # ---- # ---- # ----
472
473 import AnnounceListenManager Timer/Periodic
474
475 #
476 # rvicClient message interface
477 #
478 Class ALM/RvicClient -superclass AnnounceListenManager
479
480 #
481 ALM/RvicClient public init {spec parent {mtu 1500}} {
482
483 set port_ [lindex [split $spec "/"] 1]
484 set addr "[lindex [split $spec "/"] 0]/"
485 if {[string first / $spec] == -1} {
486 set port_ $spec
487 set addr ""
488 }
489 # addressblocks only allow even ports -- emulate this
490 if {$port_ % 2 != 0} {
491 puts "WARNING: you specified an odd port: decrementing 1"
492 incr port_ -1
493 set spec "$addr$port_"
494 }
495
496 eval [list $self] next $spec $mtu
497
498 $self instvar parent_
499 set parent_ $parent
500 }
501
502 #
503 # receive updates from rvic server
504 #
505 ALM/RvicClient private recv_announcement {addr port data size} {
506 #puts "Msg: $addr/$port\[$size\]: [lrange $data 0 0]"
507 $self instvar parent_
508
509 if {[string first "MonitorStyleList" $data] ==0} {
510 # this blows away the "\n"s
511 set data [lrange $data 1 end]
512 $parent_ update_layouts_list $data
513 } elseif {[string first "SourceList" $data] ==0} {
514 set data [split $data "\n"]
515 set data [lrange $data 1 end]
516 $parent_ update_src_list $data
517 } elseif {[string first "MonitorStyle" $data] ==0} {
518 set data [lrange $data 1 end]
519 $parent_ set_local_layout $data
520 } elseif {[string first "VideoWindow" $data] ==0} {
521 set lines [split $data "\n"]
522 set lines [lrange $lines 1 end]
523 set counter 1
524 foreach i $lines {
525 $parent_ set_button_label $counter [lrange $i 1 end]
526 incr counter
527 }
528 } elseif {[string first "Autoswitchlayout" $data] ==0} {
529 $parent_ set_layout_switching [lindex $data 1]
530 } elseif {[string first "VoiceSwitchList" $data] ==0} {
531 $parent_ update_vs_checkbuttons $data
532 } elseif {[string first "TimerSwitchList" $data] ==0} {
533 $parent_ update_ts_checkbuttons $data
534 } elseif {[string first "SessionAddress" $data] ==0} {
535 set data [split $data "\n"]
536 set data [lrange $data 1 end]
537 $parent_ update_src_address $data
538 } else {
539 puts "Unknown msg from $addr/$port\[$size\]: $data"
540 }
541 #$parent_ refresh_ui
542 }
543
544 #
545 # alternates through all the state update messages
546 #
547 ALM/RvicClient private send_announcement {} {
548 $self instvar whichMsg_ parent_
549
550 if {![info exists whichMsg_]} {
551 set whichMsg_ -1
552 }
553 incr whichMsg_ 1
554 if {$whichMsg_ > 7} {set whichMsg_ 0}
555
556 switch $whichMsg_ {
557 0 {set msg "Get SourceList"}
558 1 {set msg "Get MonitorStyleList"}
559 2 {set msg "Set MonitorStyle"}
560 3 {set msg "Set VideoWindow"}
561 4 {set msg "Set Autoswitchlayout [$parent_ set_layout_switching]"}
562 5 {set msg "Set TimerSwitchList"}
563 6 {set msg "Set VoiceSwitchList"}
564 7 {set msg "Get SessionAddress"}
565 }
566 $self announce $msg
567 }
568
569 #
570 # sends all messages necessary to update all state
571 #
572 ALM/RvicClient private request_full_update {} {
573 set an "Get MonitorStyleList"
574 append an "\nGet SourceList"
575 append an "\nSet MonitorStyle"
576 append an "\nSet VideoWindow"
577 append an "\nSet Autoswitchlayout"
578 append an "\nSet TimerSwitchList"
579 append an "\nSet VoiceSwitchList"
580 append an "\nGet SessionAddress"
581 $self announce $an
582 }
583
584 #
585 # set remote vic's session address
586 #
587 ALM/RvicClient public switch_address {address} {
588 set msg "Set SessionAddress $address"
589 $self announce $msg
590 }
591
592
593
594
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.