1 # ui-recorder.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
32 import ImageTextButton Dialog Observer ScrolledWindow/Expand DropDown ScrolledListbox DirectoryBox VcrIcons
33
34 WidgetClass RecorderUI/Input -superclass Dialog -default {
35 { .title "Recorder" }
36 { .address.width 15 }
37 { .listbox.scrollbar both }
38 { .listbox.selectMode multiple }
39 { .listbox.bbox.width 225 }
40 { .listbox.bbox.height 150 }
41 { .listbox*Label.borderWidth 1 }
42 { .listbox.bbox.highlightThickness 1 }
43 { .listbox.Scrollbar.borderWidth 1 }
44 { .listbox.Scrollbar.highlightThickness 1 }
45 { .listbox.Scrollbar.width 10 }
46 { .listbox.borderWidth 1 }
47 { .listbox.relief sunken }
48
49 { *Menubutton.borderWidth 1 }
50 { *Menubutton.highlightThickness 1 }
51 { *Entry.borderWidth 1 }
52 { *Entry.highlightThickness 1 }
53 { .protocol.button.anchor w }
54 { .media.borderWidth 1 }
55 { .media.relief raised }
56 { .media.highlightThickness 1 }
57 { .media.entry.borderWidth 0 }
58 { .media.entry.highlightThickness 0 }
59 { .media.entry.relief flat }
60 { .media.button.borderWidth 0 }
61 { .media.button.highlightThickness 0 }
62
63 { *ImageTextButton.borderWidth 1 }
64 { *ImageTextButton.highlightThickness 1 }
65 { *ImageTextButton.orient horizontal }
66 { *font WidgetDefault }
67 { *LabeledWidget.label.font WidgetDefault(-boldfont) }
68 { *dirbox.entry_label.font WidgetDefault(-boldfont) }
69 }
70
71 # { *Entry.background White }
72 # { *listbox*window.background White }
73 # { *listbox*bbox.background White }
74 # { *listbox*Label.normalBackground White }
75 # { *dirbox*window.background White }
76 # { *dirbox*bbox.background White }
77 # { *dirbox*HierarchicalListboxItem.normalBackground White }
78
79
80 RecorderUI/Input instproc destroy { } {
81 $self instvar filedlg_
82 if [info exists filedlg_] {
83 destroy $filedlg_
84 }
85 $self tkvar media_
86 catch {trace vdelete media_ w "$self media_changed_"}
87 $self next
88 }
89
90
91 RecorderUI/Input instproc build_widget { path } {
92 $self instvar protocols_
93
94 # instantiate the protocols_ array
95 set protocols_(mediaboard) SRM
96 set protocols_(video) RTP
97 set protocols_(audio) RTP
98
99 #create the enclosing frames
100 frame $path.f1
101 frame $path.f2
102
103 # create the session name box
104 entry $path.session -textvariable [$self tkvarname session_id_]
105 LabeledWidget $path.session_label -label "Session ID:" -underline 0 \
106 -orient horizontal -widget $path.session
107
108 # create the catalog file box
109 entry $path.catalog -textvariable [$self tkvarname catalog_filename_]
110 LabeledWidget $path.catalog_label -label "Catalog file:" -underline 0 \
111 -orient horizontal -widget $path.catalog
112 ImageTextButton $path.catalog_browse -image Icons(browse) -text \
113 "Browse" -underline 0 -command "$self browse_catalog_"
114
115 # create a separator
116 frame $path.sep1 -bd 1 -relief groove -height 2
117
118 # create the media selection widget
119 DropDown $path.protocol -variable [$self tkvarname protocol_]
120 $path.protocol insert end RTP SRM
121 LabeledWidget $path.protocol_label -label Protocol: -underline 0 \
122 -orient horizontal -widget $path.protocol
123
124 # create the media selection widget
125 DropDown/Text $path.media -variable [$self tkvarname media_]
126 eval [list $path.media] insert end [lsort [array names protocols_]]
127 LabeledWidget $path.media_label -label Media: -underline 3 \
128 -orient horizontal -widget $path.media
129
130 # create the address entry box
131 entry $path.address -textvariable [$self tkvarname addr_]
132 LabeledWidget $path.address_label -label Address: -underline 4 \
133 -orient horizontal -widget $path.address
134
135 # create the listbox
136 ScrolledListbox $path.listbox -browsecmd "$self browse_listbox; \
137 $self ignore_args"
138
139 # create the directory entry box
140 DirectoryBox $path.dirbox
141 $path.dirbox subwidget entry_label configure -text "Save in:"
142
143 # create the various buttons
144 frame $path.buttons
145 ImageTextButton $path.add -image Icons(plus) -text Add -underline 0 \
146 -command "$self add"
147 ImageTextButton $path.delete -image Icons(trashcan) -text Delete \
148 -underline 0 -state disabled -command "$self delete"
149 ImageTextButton $path.record -image VcrIcons(record) -text Record \
150 -underline 0 -state disabled \
151 -command "$self config -result record"
152 ImageTextButton $path.cancel -image Icons(cross) -text Cancel \
153 -command "$self cancel"
154
155 # pack all the widgets in
156 pack $path.cancel $path.record $path.delete $path.add -side right \
157 -padx 3 -fill x -in $path.buttons
158
159 pack $path.dirbox -fill both -expand 1 -side top -in $path.f1
160 pack $path.buttons -fill x -side bottom -pady 3 -in $path.f1 -anchor e
161
162 pack $path.session_label -fill x -side top -in $path.f2
163 pack $path.catalog_label -fill x -side top -in $path.f2
164 pack $path.catalog_browse -anchor e -side top -in $path.f2
165 pack $path.sep1 -fill x -side top -in $path.f2 -pady 2
166 pack $path.protocol_label -fill x -side top -in $path.f2
167 pack $path.media_label -fill x -side top -in $path.f2
168 pack $path.address_label -fill x -side top -in $path.f2
169 pack $path.listbox -fill both -expand 1 -side top -in $path.f2
170
171 pack $path.f2 $path.f1 -side left -fill both -expand 1 -padx 5 -pady 5
172
173 # set up a trace on the media_ variable, so we can modify the protocol
174 # whenever the media changes
175
176 $self tkvar addr_ session_id_ media_ catalog_filename_
177 trace variable media_ w "$self media_changed_"
178
179 set addr_ "224.2.55.66/8001"
180
181 # use the current date/time as the default session-id
182 set session_id_ [clock format [clock seconds] -format "%m%d%H%M"]
183 set catalog_filename_ "cat.ctg"
184 set media_ "mediaboard"
185
186 # set up all key bindings
187 bind $path <Key-Escape> "$self subwidget cancel invoke_with_ui"
188 $self bindkey_ a "if \{\[$path.add cget -state\]!={disabled}\} \{ \
189 focus $path.add; $path.add invoke_with_ui \}"
190 $self bindkey_ d "if \{\[$path.delete cget -state\]!={disabled}\} \{ \
191 focus $path.delete; $path.delete invoke_with_ui \}"
192 $self bindkey_ r "if \{\[$path.record cget -state\]!={disabled}\} \{ \
193 focus $path.record; $path.record invoke_with_ui \}"
194 $self bindkey_ b "if \{\[$path.catalog_browse cget -state\]!=\
195 {disabled}\} \{ focus $path.catalog_browse; \
196 $path.catalog_browse invoke_with_ui \}"
197 $self bindkey_ s "focus $path.session"
198 $self bindkey_ h "focus $path.catalog"
199 $self bindkey_ p "focus [$path.protocol subwidget button]"
200 $self bindkey_ i "focus [$path.media subwidget entry]"
201 $self bindkey_ e "focus $path.address"
202 $self bindkey_ v "focus [$self subwidget dirbox subwidget entry]"
203 }
204
205
206 RecorderUI/Input instproc bindkey_ { key script } {
207 set path [$self info path]
208 bind $path <Alt-[string tolower $key]> $script
209 bind $path <Alt-[string toupper $key]> $script
210 }
211
212
213
214 RecorderUI/Input instproc add { } {
215 $self tkvar protocol_ media_ addr_
216 set addr_ [string trim $addr_]
217 if { $addr_!={} } {
218 if { ![catch {$self subwidget listbox insert end \
219 "-id $protocol_+$media_+$addr_ \
220 $protocol_: $media_ ($addr_)"}] } {
221 $self subwidget record configure -state normal
222 }
223 }
224 }
225
226
227 RecorderUI/Input instproc delete { } {
228 set listbox [$self subwidget listbox]
229 foreach id [$listbox selection get] {
230 $listbox delete -id $id
231 }
232
233 $self subwidget delete configure -state disabled
234 if { [$listbox info numelems] <= 0 } {
235 $self subwidget record configure -state disabled
236 }
237 }
238
239
240 RecorderUI/Input instproc browse_listbox { } {
241 if { [llength [$self subwidget listbox selection get]]==0 } {
242 $self subwidget delete configure -state disabled
243 } else {
244 $self subwidget delete configure -state normal
245 }
246 }
247
248
249 RecorderUI/Input instproc browse_catalog_ { } {
250 $self instvar filedlg_
251 if { ![info exists filedlg_] } {
252 $self tkvar catalog_filename_
253 set path [$self info path]
254 set filedlg_ [FileDialog [winfo toplevel $path].filedlg \
255 -type save -title "Catalog file name" \
256 -transient $path]
257 $filedlg_ subwidget filebox configure \
258 -filename [file tail $catalog_filename_] \
259 -filetypes "{ {Session catalog files} {.ctg} }\
260 { {All files} {*} }"
261 }
262
263 $filedlg_ subwidget filebox configure -directory \
264 [$self subwidget dirbox cget -directory]
265 set filename [$filedlg_ invoke]
266 if { $filename!="" } {
267 $self tkvar catalog_filename_
268 set catalog_filename_ $filename
269 }
270 }
271
272
273 RecorderUI/Input instproc add_direct { protocol media addr } {
274 $self tkvar media_ addr_
275 set media_ $media
276 set addr_ $addr
277 set protocol_ $protocol
278 $self add
279 }
280
281
282 RecorderUI/Input instproc set_session_id { session_id } {
283 $self tkvar session_id_
284 set session_id_ $session_id
285 }
286
287
288 RecorderUI/Input instproc set_catalog_filename { filename } {
289 $self tkvar catalog_filename_
290 set catalog_filename_ $filename
291 }
292
293
294 RecorderUI/Input instproc set_directory { directory } {
295 $self subwidget dirbox configure -directory $directory
296 }
297
298
299 RecorderUI/Input instproc get_session_id { } {
300 $self tkvar session_id_
301 return $session_id_
302 }
303
304
305 RecorderUI/Input instproc get_catalog_filename { } {
306 $self tkvar catalog_filename_
307 if { $catalog_filename_=="" } {
308 return ""
309 } else {
310 return [file join [$self get_directory] $catalog_filename_]
311 }
312 }
313
314
315 RecorderUI/Input instproc get_directory { } {
316 return [$self subwidget dirbox cget -directory]
317 }
318
319
320 RecorderUI/Input instproc media_changed_ { args } {
321 $self tkvar media_ protocol_
322 $self instvar protocols_
323 set media [string tolower $media_]
324 if { [info exists protocols_($media)] } {
325 set protocol_ $protocols_($media)
326 }
327 }
328
329
330
331 WidgetClass RecorderUI/Stream -superclass Observer -configspec {
332 { -minimized minimized Minimized 0 config_minimized }
333 { -name name Name {unknown} config_option }
334 { -filename filename Filename {unknown} config_option }
335 { -bytes bytes Bytes {0} config_option }
336 } -default {
337 { .borderWidth 1 }
338 { .relief groove }
339 { *Button.padY 0 }
340 { *Button.borderWidth 0 }
341 { *Button.highlightThickness 1 }
342 { *Button.activeBackground WidgetDefault(-background) }
343 { *Label.padY 0 }
344 { *Label.borderWidth 0 }
345 { *font WidgetDefault }
346 { *LabeledWidget.label.font WidgetDefault(-boldfont) }
347 { .name.font WidgetDefault(-boldfont) }
348 }
349
350
351 RecorderUI/Stream instproc destroy { } {
352 $self instvar after_id_
353 if [info exists after_id_] {
354 after cancel $after_id_
355 unset after_id_
356 }
357 $self next
358 }
359
360
361 RecorderUI/Stream instproc build_widget { path } {
362 frame $path.f1
363 frame $path.f2
364
365 button $path.minimize -command "\
366 if \{ \[$self cget -minimized\] \} \{ \
367 $self configure -minimized 0 \} else \{ \
368 $self configure -minimized 1 \}"
369 label $path.name -anchor w
370 pack $path.minimize -side left -fill y -in $path.f1
371 pack $path.name -side left -fill both -expand 1 -in $path.f1
372
373 label $path.filename -anchor w
374 LabeledWidget $path.filename_label -label "Filename:" \
375 -widget $path.filename
376 label $path.bytes -anchor w
377 LabeledWidget $path.bytes_label -label "Bytes received:" \
378 -widget $path.bytes
379 pack $path.filename_label -side top -fill x -in $path.f2 -padx 20
380 pack $path.bytes_label -side top -fill x -in $path.f2 -padx 20
381
382 pack $path.f1 -fill x
383 pack $path.f2 -fill x -expand 1
384 }
385
386
387 RecorderUI/Stream instproc disable { } {
388 set fg [WidgetClass widget_default -disabledforeground]
389 $self subwidget name configure -fg $fg
390 $self subwidget filename configure -fg $fg
391 $self subwidget bytes configure -fg $fg
392 $self subwidget filename_label subwidget label configure -fg $fg
393 $self subwidget bytes_label subwidget label configure -fg $fg
394
395 $self instvar stream_
396 if { [info exists stream_] } {
397 delete $stream_
398 unset stream_
399 }
400 }
401
402
403 RecorderUI/Stream instproc config_minimized { option args } {
404 set path [$self info path]
405 if { [llength $args]==0 } {
406 if { [lsearch [pack slaves $path] $path.f2] != -1 } {
407 return 0
408 } else {
409 return 1
410 }
411 } else {
412 set value [lindex $args 0]
413 if { $value } {
414 catch { pack forget $path.f2 }
415 $path.minimize configure -image Icons(maximize)
416 } else {
417 if { [lsearch [pack slaves $path] $path.f2] == -1 } {
418 pack $path.f2 -fill x -expand 1
419 }
420 $path.minimize configure -image Icons(minimize)
421 }
422 }
423 }
424
425
426 RecorderUI/Stream instproc config_option { option args } {
427 set subwidget [string range $option 1 end]
428 if { [llength $args]==0 } {
429 return [$self subwidget $subwidget cget -text]
430 } else {
431 $self subwidget $subwidget configure -text [lindex $args 0]
432 }
433 }
434
435
436 RecorderUI/Stream instproc attach_stream { stream } {
437 $self set stream_ $stream
438 }
439
440
441 WidgetClass RecorderUI/Session -superclass { Observer ScrolledWindow/Expand }
442
443
444 RecorderUI/Session instproc build_widget { path } {
445 $self next $path
446 $self set count_ 0
447 }
448
449
450 RecorderUI/Session instproc disable { } {
451 foreach widget [winfo children [$self subwidget window]] {
452 $widget disable
453 }
454
455 #delete [$self set session_]
456 }
457
458
459 RecorderUI/Session instproc attach_session { session } {
460 $self set session_ $session
461 }
462
463
464 WidgetClass RecorderUI/Status -superclass Dialog -default {
465 { .title "Recorder" }
466 { .modal 0 }
467 { *session_list.scrollbar both }
468 { *session_list.borderWidth 1 }
469 { *session_list.relief sunken }
470 { *session_list*Label.borderWidth 1 }
471 { *session_list.bbox.highlightThickness 1 }
472 { *session_list.Scrollbar.borderWidth 1 }
473 { *session_list.Scrollbar.highlightThickness 1 }
474 { *session_list.Scrollbar.width 10 }
475 { *session_list.bbox.width 225 }
476
477 { *RecorderUI/Session.scrollbar both }
478 { *RecorderUI/Session.borderWidth 1 }
479 { *RecorderUI/Session.relief sunken }
480 { *RecorderUI/Session.bbox.highlightThickness 1 }
481 { *RecorderUI/Session.Scrollbar.borderWidth 1 }
482 { *RecorderUI/Session.Scrollbar.highlightThickness 1 }
483 { *RecorderUI/Session.Scrollbar.width 10 }
484
485 { *Entry.borderWidth 1 }
486 { *Entry.width 5 }
487 { *ImageTextButton.borderWidth 1 }
488 { *ImageTextButton.highlightThickness 1 }
489 }
490
491
492
493
494 RecorderUI/Status instproc build_widget { path } {
495 frame $path.f1
496 frame $path.f2
497
498 entry $path.session_id
499 LabeledWidget $path.session_id_label -label "Session ID:" \
500 -orient horizontal -widget $path.session_id
501
502 entry $path.directory
503 LabeledWidget $path.directory_label -label "Save in:" \
504 -orient horizontal -widget $path.directory
505
506 entry $path.catalog
507 LabeledWidget $path.catalog_label -label "Catalog file:" \
508 -orient horizontal -widget $path.catalog
509
510 ScrolledListbox $path.session_list -browsecmd "$self browse"
511 frame $path.session_ui
512 frame $path.buttons
513
514 # FIXME - this widget never gets enabled when recording starts - I don't
515 # think this even works if enabled
516 ImageTextButton $path.stop -image VcrIcons(stop) \
517 -text "Stop this session" -command "$self stop" \
518 -state disabled
519 ImageTextButton $path.exit -image Icons(cross) -text "Exit" \
520 -command "$self stop_all"
521
522 pack $path.exit $path.stop -fill x -anchor e -in $path.buttons \
523 -side right
524
525 pack $path.session_id_label -side top -fill x -in $path.f2
526 pack $path.directory_label -side top -fill x -in $path.f2
527 pack $path.catalog_label -side top -fill x -in $path.f2
528 pack $path.session_list -fill both -expand 1 -side top -in $path.f2
529 pack $path.f2 -fill both -side left -in $path.f1 -padx 5 -pady 5
530 pack $path.session_ui -fill both -expand 1 -side right -in $path.f1 \
531 -padx 5 -pady 5
532
533 pack $path.buttons -side bottom -fill x -anchor e
534 pack $path.f1 -side top -fill both -expand 1
535 $self set count_ 0
536 }
537
538
539 RecorderUI/Status instproc add { session } {
540 $self instvar count_ stop_status_
541 set widget [RecorderUI/Session \
542 [$self subwidget session_ui].session_$count_]
543 incr count_
544 set stop_status_($widget) 0
545 set list [$self subwidget session_list]
546 $list insert end "-id $widget $session"
547 if { [llength [$list selection get]]==0 } {
548 $list selection set -id $widget
549 $self browse $widget
550 }
551 return $widget
552 }
553
554
555 RecorderUI/Status instproc stop { {widget {}} } {
556 $self instvar stop_status_
557 set list [$self subwidget session_list]
558 if { $widget=={} } {
559 set widget [$list selection get]
560 if { $widget=={} } return
561 }
562
563 set list_widget [$list info widget -id $widget]
564 $list_widget configure -normalforeground [WidgetClass \
565 widget_default -disabledforeground]
566 $list_widget configure -selectforeground [WidgetClass \
567 widget_default -disabledforeground]
568 $widget disable
569 set stop_status_($widget) 1
570 $self subwidget stop configure -state disabled
571 }
572
573
574 RecorderUI/Status instproc stop_all { } {
575 foreach widget [$self subwidget session_list info all] {
576 $self stop $widget
577 }
578 $self configure -result "exit"
579 }
580
581
582 RecorderUI/Status instproc browse { widget } {
583 $self instvar stop_status_
584 set list [$self subwidget session_list]
585 if { [llength [$list selection get]]==0 } {
586 $list selection set -id $widget
587 }
588
589 catch { pack forget [pack slaves [$self subwidget session_ui]] }
590 pack $widget -fill both -expand 1
591
592 if { $stop_status_($widget) } {
593 $self subwidget stop configure -state disabled
594 } else {
595 #$self subwidget stop configure -state normal
596 # FIXME stop always core dumps, so temp disable it
597 }
598 }
599
600
601
602
603
604
605 # observer methods!
606
607
608 RecorderUI/Session instproc new_stream { stream } {
609 $self instvar streams_
610
611 $self instvar count_
612 set widget [RecorderUI/Stream [$self subwidget window].stream_$count_]
613 incr count_
614 pack $widget -side top -fill x -expand 1 -anchor w -padx 1 -pady 1
615
616 set streams_($stream) $widget
617 $stream attach_observer $widget
618 $widget attach_stream $stream
619 }
620
621
622 RecorderUI/Session instproc stream_done { stream } {
623 $self instvar streams_
624 if [info exists streams_($stream)] {
625 $streams_($stream) disable
626 $stream_detach_observer $streams_($stream)
627 unset streams_($stream)
628 }
629 }
630
631
632 RecorderUI/Stream instproc name { name } {
633 $self configure -name $name
634 }
635
636
637 RecorderUI/Stream instproc filename { filename } {
638 $self configure -filename $filename
639 }
640
641
642 RecorderUI/Stream instproc bytes_rcvd { bytes } {
643 $self instvar bytes_ after_id_
644 set bytes_ $bytes
645 if { ![info exists after_id_] } {
646 set after_id_ [after 1000 $self bytes_rcvd_helper]
647 }
648 }
649
650
651 RecorderUI/Stream instproc bytes_rcvd_helper { } {
652 $self instvar bytes_ after_id_
653 $self configure -bytes $bytes_
654 unset after_id_
655 }
656
657
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.