1#!/usr/bin/wish -f 2# 3# TiMidity++ -- MIDI to WAVE converter and player 4# Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> 5# Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20# 21# TkMidity -- Tcl/Tk Interface for TiMidity 22# written by Takashi IWAI 23# 24# Tk control panel routine 25# 26 27#---------------- 28# initialize global variables 29# 30proc InitGlobal {} { 31 32 global Stat tk_patchLevel 33 34 if [catch {expr $Stat(new_tcltk) == 0 || $Stat(new_tcltk) == 1}] { 35 set Stat(new_tcltk) 0 36 if [regexp "(\[0-9\]+\.\[0-9\]+)" $tk_patchLevel cur] { 37 if {$cur >= 4.0} { 38 set Stat(new_tcltk) 1 39 } 40 } 41 } 42 43 # time table and volume 44 set Stat(MaxSecs) 0 45 set Stat(LastSec) 0 46 set Stat(TotalTimeStr) "/ 0:00" 47 48 # message lines 49 set Stat(CurMsgs) 0 50 set Stat(MaxMsgs) 500 51 52 # current status 53 set Stat(Playing) 0 54 set Stat(Paused) 0 55 set Stat(Blinking) 0 56 57 # MIDI file list 58 set Stat(CurIdx) -1 59 set Stat(MaxFiles) 0 60 set Stat(FileList) {} 61 set Stat(ShuffleList) {} 62 set Stat(CurFile) "--------" 63 set Stat(NextFile) "--------" 64 65 global Config 66 # playing mode 67 set Config(Tracing) 0 68 set Config(RepeatPlay) 0 69 set Config(ShufflePlay) 0 70 set Config(AutoStart) 0 71 set Config(AutoExit) 0 72 set Config(ConfirmExit) 1 73 74 # display configuration 75 set Config(Disp:file) 1 76 set Config(Disp:time) 1 77 set Config(Disp:text) 1 78 set Config(Disp:volume) 1 79 set Config(Disp:button) 1 80 set Config(Disp:trace) 1 81 82 set Config(CurFileMode) 0 83 84 # current volume 85 set Config(CurVol) 75 86 87 wm title . "TkMidity" 88 wm iconname . "TkMidity" 89 global bitmap_path 90 wm iconbitmap . "timidity" 91} 92 93 94#---------------- 95# read a message from stdin 96# 97proc HandleInput {} { 98 global Stat Config 99 100 set mlist [gets stdin] 101 set msg [lindex $mlist 0] 102 103 if {$msg == "RSET"} { 104 if {$Config(Tracing)} { 105 TraceReset 106 } 107 } elseif {$msg == "TIME"} { 108 # set total time 109 set csecs [expr [lindex $mlist 1] / 100] 110 set mins [expr $csecs / 60] 111 set secs [expr $csecs % 60] 112 set Stat(TotalTimeStr) [format "/ %d:%02d" $mins $secs] 113 set Stat(MaxSecs) $csecs 114 set tics [expr $csecs / 8] 115 set tics [expr (($tics + 4) / 5) * 5] 116 .body.time.scale configure -tickinterval $tics -to $csecs 117 SetTime 0 118 119 } elseif {$msg == "MVOL"} { 120 # set master volume 121 SetVolume [lindex $mlist 1] 122 123 } elseif {$msg == "FILE"} { 124 # set playing file 125 set Stat(CurFile) [retrieve-filename [lindex $mlist 1]] 126 wm title . "TkMidity: $Stat(CurFile)" 127 wm iconname . "TkMidity: $Stat(CurFile)" 128 if {$Config(CurFileMode) == 0} { 129 .body.curfile configure -text "$Stat(CurFile) / 00:00" 130 } else { 131 .body.curfile configure -text "$Stat(CurFile) / -$Stat(TotalTimeStr)" 132 } 133 AppendMsg "------" 134 135 } elseif {$msg == "LIST"} { 136 # set file list 137 .body.file.list delete 0 end 138 set Stat(MaxFiles) [lindex $mlist 1] 139 set Stat(FileList) {} 140 for {set i 0} {$i < $Stat(MaxFiles)} {incr i} { 141 set file [gets stdin] 142 .body.file.list insert end $file 143 lappend Stat(FileList) $file 144 } 145 146 set Stat(CurIdx) -1 147 SelectNumber 148 149 } elseif {$msg == "ALST"} { 150 # append file list 151 set i $Stat(MaxFiles) 152 set Stat(MaxFiles) [expr $i + [lindex $mlist 1]] 153 for {} {$i < $Stat(MaxFiles)} {incr i} { 154 set file [gets stdin] 155 .body.file.list insert end $file 156 if {$Config(ShufflePlay)} { 157 lappend Stat(ShuffleList) [llength $Stat(FileList)] 158 } 159 lappend Stat(FileList) $file 160 } 161 .body.file.list select set $Stat(CurIdx) 162 163 } elseif {$msg == "ERRR"} { 164 # delete file list 165 .body.file.list delete $Stat(CurIdx) 166 set Stat(MaxFiles) [expr $Stat(MaxFiles) - 1] 167 set tmplist {} 168 for {set i 0} {$i < $Stat(CurIdx)} {incr i} { 169 lappend tmplist [lindex $Stat(FileList) $i] 170 } 171 for {set i $Stat(CurIdx)} {$i < $Stat(MaxFiles)} {incr i} { 172 lappend tmplist [lindex $Stat(FileList) [expr $i + 1]] 173 } 174 set Stat(FileList) {} 175 for {set i 0} {$i < $Stat(MaxFiles)} {incr i} { 176 lappend Stat(FileList) [lindex $tmplist $i] 177 } 178 if {$Stat(CurIdx) >= $Stat(MaxFiles)} { 179 if {$Config(RepeatPlay)} { 180 set Stat(CurIdx) 0 181 } elseif {$Config(AutoExit)} { 182 QuitCmd 183 } else { 184 StopCmd 185 } 186 } 187 SelectNumber 188 189 } elseif {$msg == "PREV"} { 190 # previous file 191 set Stat(CurIdx) [expr $Stat(CurIdx) - 1] 192 if {$Stat(CurIdx) < 0} {set Stat(CurIdx) 0} 193 SelectNumber 194 195 } elseif {$msg == "NEXT"||$msg == "TEND"} { 196 # next file 197 incr Stat(CurIdx) 198 if {$Stat(CurIdx) >= $Stat(MaxFiles)} { 199 if {$Config(RepeatPlay)} { 200 set Stat(CurIdx) 0 201 } elseif {$Config(AutoExit)} { 202 QuitCmd 203 } else { 204 StopCmd 205 } 206 } 207 SelectNumber 208 209 } elseif {$msg == "CMSG"} { 210 # put message 211 set type [lindex $mlist 1] 212 set str [gets stdin] 213 AppendMsg $str 214 215 } elseif {$msg == "LYRC"} { 216 # put message 217 set type [lindex $mlist 1] 218 set str [gets stdin] 219 .body.text.buf insert end $str 220 221 } elseif {$msg == "CERR"} { 222 error [format "%s: %s" $Stat(NextFile) [gets stdin]] 223 WriteMsg "NEXT" 224 225 } elseif {$msg == "QUIT"} { 226 # quit 227 exit 228 } elseif {$msg == "RSTA"} { 229 # restart file 230 SelectNumber 231 } 232} 233 234 235#---------------- 236# make shuffled list 237# 238proc MakeShuffleList {} { 239 global Stat 240 set Stat(ShuffleList) {} 241 for {set i 0} {$i < $Stat(MaxFiles)} {incr i} { 242 lappend Stat(ShuffleList) $i 243 } 244 set len [expr $Stat(MaxFiles) - 1] 245 while {$len > 0} { 246 set pos [my-random [expr $len + 1]] 247 set tmp [lindex $Stat(ShuffleList) $pos] 248 set Stat(ShuffleList) [lreplace $Stat(ShuffleList) $pos $pos \ 249 [lindex $Stat(ShuffleList) $len]] 250 set Stat(ShuffleList) [lreplace $Stat(ShuffleList) $len $len $tmp] 251 set len [expr $len - 1] 252 } 253} 254 255# 256# append a string to message buffer 257# 258proc AppendMsg {str} { 259 global Stat 260 261 incr Stat(CurMsgs) 262 if {$Stat(CurMsgs) >= $Stat(MaxMsgs)} { ClearMsg } 263 .body.text.buf insert end $str\n 264 .body.text.buf yview -pickplace end 265} 266 267# 268# clear message buffer 269# 270proc ClearMsg {} { 271 global Stat 272 .body.text.buf delete 0.0 end 273 .body.text.buf yview 0 274 set Stat(CurMsgs) 0 275} 276 277 278#---------------- 279# select the file in listbox and load it 280# 281proc SelectNumber {} { 282 global Stat Config 283 if {$Stat(new_tcltk)} { 284 .body.file.list select clear 0 end 285 } else { 286 .body.file.list select clear 287 } 288 set idx -1 289 if {$Stat(CurIdx) >= 0 && $Stat(CurIdx) < [llength $Stat(FileList)]} { 290 if {$Config(ShufflePlay)} { 291 if {$Stat(ShuffleList) == {}} { 292 MakeShuffleList 293 } 294 set idx [lindex $Stat(ShuffleList) $Stat(CurIdx)] 295 } else { 296 set idx $Stat(CurIdx) 297 } 298 set thefile [lindex $Stat(FileList) $idx] 299 set Stat(NextFile) $thefile 300 } 301 302 if {$idx >= 0} { 303 if {$Stat(new_tcltk)} { 304# .body.file.list select set $idx 305 } else { 306# .body.file.list select from $idx 307# .body.file.list select to $idx 308 } 309 .body.curfile configure -text\ 310 "Playing: [lindex $Stat(FileList) $idx]" 311 LoadCmd $idx 312 set Stat(Playing) 1 313 } else { 314 SetTime 0 315 .body.curfile configure -text "-------- / 00:00" 316 set Stat(Playing) 0 317 set Stat(Paused) 0 318 } 319 DispButtonPlay 320} 321 322 323# 324# update current time 325# 326proc SetTime {val} { 327 global Stat Config 328 if {$Stat(CurIdx) == -1} { 329 return 330 } 331 set Stat(LastSec) $val 332 if {$Config(CurFileMode) == 0} { 333 set curt [sec2time $val] 334 .body.curfile configure\ 335 -text "$Stat(CurFile) / $curt" 336 } else { 337 set curt [sec2time [expr $val - $Stat(MaxSecs)]] 338 .body.curfile configure\ 339 -text "$Stat(CurFile) / $curt" 340 } 341 set curt [sec2time $val] 342 .body.time.label configure\ 343 -text "$curt / $Stat(TotalTimeStr)" 344 .body.time.scale set $val 345 DispButtonPlay 346} 347 348 349# 350# colorize buttons with each state 351# 352proc DispButtonPlay {} { 353 global Stat 354 if {$Stat(Playing)} { 355 if {$Stat(Blinking)} { 356 set color green 357 set Stat(Blinking) 0 358 } else { 359 set color red 360 set Stat(Blinking) 1 361 } 362 .body.button.play configure -fg $color -activeforeground $color 363 } else { 364 .body.button.play configure -fg black -activeforeground black 365 } 366 367 if {$Stat(Playing) && $Stat(Paused)} { 368 .body.button.pause configure -fg red -activeforeground red 369 } else { 370 .body.button.pause configure -fg black -activeforeground black 371 } 372} 373 374 375# 376# update current volume 377# 378proc SetVolume {val} { 379 global Config 380 set Config(CurVol) $val 381 .body.volume.scale set $val 382} 383 384 385#---------------- 386# write message 387# messages are: PREV, NEXT, QUIT, FWRD, BACK, RSET, STOP 388# LOAD\n<filename>, JUMP <time>, VOLM <volume> 389# 390 391proc WriteMsg {str} { 392 puts stdout $str 393 flush stdout 394} 395 396 397#---------------- 398# callback commands 399# 400 401# 402# jump to specified time 403# 404proc JumpCmd {val} { 405 global Stat 406 if {$val != $Stat(LastSec)} { 407 WriteMsg [format "JUMP %d" [expr $val * 100]] 408 } 409} 410 411# 412# change volume amplitude 413# 414proc VolumeCmd {val {force 0}} { 415 global Config 416 if {$val < 0} {set val 0} 417 if {$val > 200} {set val 200} 418 if {$force != 0 || $val != $Config(CurVol)} { 419 WriteMsg [format "VOLM %d" $val] 420 } 421} 422 423# 424# load the specified file 425# 426proc LoadCmd {idx} { 427 global Stat Config 428 WriteMsg "LOAD" 429 WriteMsg [lindex $Stat(FileList) $idx] 430 AppendMsg "" 431} 432 433# 434# play the first file 435# 436proc PlayCmd {} { 437 global Stat 438 if {$Stat(Playing) == 0} { 439 WriteMsg "NEXT" 440 } 441} 442 443proc PauseCheck {} { 444 global Stat 445 if {$Stat(Paused)} { 446 set Stat(Paused) 0 447 } 448 DispButtonPlay 449} 450 451# 452# pause music 453# 454proc PauseCmd {} { 455 global Stat 456 if {$Stat(Playing)} { 457 if {$Stat(Paused)} { 458 set Stat(Paused) 0 459 } else { 460 set Stat(Paused) 1 461 } 462 DispButtonPlay 463 WriteMsg "STOP" 464 } 465} 466 467# 468# stop playing 469# 470proc StopCmd {} { 471 global Stat Config 472 if {$Stat(Playing)} { 473 WriteMsg "QUIT" 474 WriteMsg "XTND" 475 set Stat(CurIdx) -1 476 SelectNumber 477 if {$Config(Tracing)} { 478 TraceReset 479 } 480 wm title . "TkMidity" 481 wm iconname . "TkMidity" 482 } 483} 484 485# 486# quit TkMidity 487# 488proc QuitCmd {} { 489 global Config Stat 490 if {$Config(AutoExit) || !$Config(ConfirmExit)} { 491 WriteMsg "QUIT" 492 WriteMsg "ZAPP" 493 return 494 } 495 set oldpause $Stat(Paused) 496 if {!$oldpause} {PauseCmd} 497 if {[question "Really Quit TkMidity?" 0]} { 498 WriteMsg "QUIT" 499 WriteMsg "ZAPP" 500 return 501 } 502 if {!$oldpause} {PauseCmd} 503} 504 505# 506# play previous file 507# 508proc PrevCmd {} { 509 global Stat Config 510 if {$Stat(Playing)} { 511 WriteMsg "PREV" 512 PauseCheck 513 } 514 VolumeCmd $Config(CurVol) 1 515} 516 517# 518# play next file 519# 520proc NextCmd {} { 521 global Stat Config 522 if {$Stat(Playing)} { 523 WriteMsg "NEXT" 524 PauseCheck 525 } 526 VolumeCmd $Config(CurVol) 1 527} 528 529# 530# forward/backward 2 secs 531# 532proc ForwardCmd {} { 533 global Stat 534 if {$Stat(Playing)} { 535 WriteMsg "FWRD" 536 PauseCheck 537 } 538} 539 540proc BackwardCmd {} { 541 global Stat 542 if {$Stat(Playing)} { 543 WriteMsg "BACK" 544 PauseCheck 545 } 546} 547 548 549# 550# volume up/down 551# 552proc VolUpCmd {} { 553 global Stat Config 554 if {$Stat(Playing)} { 555 VolumeCmd [expr $Config(CurVol) + 5] 556 } 557} 558 559proc VolDownCmd {} { 560 global Stat Config 561 if {$Stat(Playing)} { 562 VolumeCmd [expr $Config(CurVol) - 5] 563 } 564} 565 566#---------------- 567# display configured tables 568# 569proc DispTables {} { 570 global Config 571 set allitems {file time text volume button trace} 572 573 foreach i $allitems { 574 pack forget .body.$i 575 if {$Config(Disp:$i)} { 576 pack .body.$i -side top -fill x 577 } 578 } 579} 580 581# 582# save configuration and playing mode 583# 584proc SaveConfig {} { 585 global Config ConfigFile 586 set fd [open $ConfigFile w] 587 if {$fd != ""} { 588 puts $fd "global Config" 589 foreach i [array names Config] { 590 puts $fd "set Config($i) $Config($i)" 591 } 592 close $fd 593 } 594} 595 596# 597# load configuration file 598# 599proc LoadConfig {} { 600 global ConfigFile Stat 601 catch {source $ConfigFile} 602} 603 604# 605# from command line 606# 607proc InitCmdLine {argc argv} { 608 global Config 609 set Config(Disp:trace) 0 610 for {set i 0} {$i < $argc} {incr i} { 611 if {[lindex $argv $i] == "-mode"} { 612 incr i 613 set mode [lindex $argv $i] 614 if {$mode == "trace"} { 615 set Config(Tracing) 1 616 set Config(Disp:trace) 1 617 } elseif {$mode == "shuffle"} { 618 set Config(ShufflePlay) 1 619 } elseif {$mode == "normal"} { 620 set Config(ShufflePlay) 0 621 } elseif {$mode == "autostart"} { 622 set Config(AutoStart) 1 623 } elseif {$mode == "autoexit"} { 624 set Config(AutoExit) 1 625 } elseif {$mode == "repeat"} { 626 set Config(RepeatPlay) 1 627 } 628 } 629 } 630} 631 632 633# 634# selection callback of the playing file from listbox 635# 636proc SelectList {lw pos} { 637 global Config Stat 638 set idx [$lw nearest $pos] 639 if {$idx >= 0 && $idx < $Stat(MaxFiles)} { 640 if {$Config(ShufflePlay)} { 641 set found [lsearch -exact $Stat(ShuffleList) $idx] 642 if {$found != -1} { 643 set Stat(CurIdx) $found 644 } 645 } else { 646 set Stat(CurIdx) $idx 647 } 648 set Stat(Playing) 1 649 PauseCheck 650 SelectNumber 651 } 652} 653 654 655# 656# 657# 658proc OpenFiles {} { 659 global Stat 660 set files [filebrowser .browser "" "*.{mid*,kar,lzh,zip}"] 661 if {$files != ""} { 662 WriteMsg "XPND" 663 WriteMsg $files 664 } 665} 666 667# 668# 669# 670proc CloseFiles {} { 671 global Stat 672 if {[question "Really Clear List?" 0]} { 673 StopCmd 674 .body.file.list delete 0 end 675 set Stat(MaxFiles) 0 676 set Stat(FileList) {} 677 set Stat(ShuffleList) {} 678 } 679} 680 681proc ToggleCurFileMode {} { 682 global Config Stat 683 if {$Config(CurFileMode) == 0} { 684 set Config(CurFileMode) 1 685 } else { 686 set Config(CurFileMode) 0 687 } 688 SetTime $Stat(LastSec) 689} 690 691#---------------- 692# create main window 693# 694 695proc CreateWindow {} { 696 global Config Stat 697 698 # menu bar 699 frame .menu -relief raised -bd 1 700 pack .menu -side top -expand 1 -fill x 701 702 # File menu 703 menubutton .menu.file -text "File" -menu .menu.file.m\ 704 -underline 0 705 menu .menu.file.m 706 .menu.file.m add command -label "Open Files" -underline 0\ 707 -command OpenFiles 708 .menu.file.m add command -label "Clear List" -underline 0\ 709 -command CloseFiles 710 .menu.file.m add command -label "Save Config" -underline 0\ 711 -command SaveConfig 712 .menu.file.m add command -label "About" -underline 0\ 713 -command { 714 information "TkMidity -- TiMidty Tcl/Tk Version\n written by T.IWAI" 715 } 716 .menu.file.m add command -label "Quit" -underline 0\ 717 -command QuitCmd 718 719 # Mode menu 720 menubutton .menu.mode -text "Mode" -menu .menu.mode.m\ 721 -underline 0 722 menu .menu.mode.m 723 .menu.mode.m add check -label "Repeat" -underline 0\ 724 -variable Config(RepeatPlay) 725 .menu.mode.m add check -label "Shuffle" -underline 0\ 726 -variable Config(ShufflePlay) -command { 727 if {$Config(ShufflePlay)} { 728 MakeShuffleList 729 } else { 730 set Stat(ShuffleList) {} 731 } 732 } 733 .menu.mode.m add check -label "Auto Start" -underline 5\ 734 -variable Config(AutoStart) 735 .menu.mode.m add check -label "Auto Exit" -underline 5\ 736 -variable Config(AutoExit) 737 .menu.mode.m add check -label "Confirm Quit" -underline 0\ 738 -variable Config(ConfirmExit) 739 740 # Display menu 741 menubutton .menu.disp -text "Display" -menu .menu.disp.m\ 742 -underline 0 743 menu .menu.disp.m 744 .menu.disp.m add check -label "File List" -underline 0\ 745 -variable Config(Disp:file) -command "DispTables" 746 .menu.disp.m add check -label "Time" -underline 0\ 747 -variable Config(Disp:time) -command "DispTables" 748 .menu.disp.m add check -label "Messages" -underline 0\ 749 -variable Config(Disp:text) -command "DispTables" 750 .menu.disp.m add check -label "Volume" -underline 0\ 751 -variable Config(Disp:volume) -command "DispTables" 752 .menu.disp.m add check -label "Buttons" -underline 0\ 753 -variable Config(Disp:button) -command "DispTables" 754 if {$Config(Tracing)} { 755 .menu.disp.m add check -label "Trace" -underline 1\ 756 -variable Config(Disp:trace) -command "DispTables" 757 } 758 759 pack .menu.file .menu.mode .menu.disp -side left 760 761 # display body 762 if {$Stat(new_tcltk)} { 763 frame .body -relief flat 764 } else { 765 frame .body -relief raised -bd 1 766 } 767 pack .body -side top -expand 1 -fill both 768 769 # current playing file 770 button .body.curfile -text "-------- / 00:00" -relief ridge\ 771 -command "ToggleCurFileMode" 772 pack .body.curfile -side top -expand 1 -fill x 773 774 # playing files list 775 frame .body.file -relief raised -bd 1 776 scrollbar .body.file.bar -relief sunken\ 777 -command ".body.file.list yview" 778 pack .body.file.bar -side right -fill y 779 if {$Stat(new_tcltk)} { 780 listbox .body.file.list -width 36 -height 10 -relief sunken -bd 2\ 781 -yscroll ".body.file.bar set" 782 } else { 783 listbox .body.file.list -geometry 36x10 -relief sunken -bd 2\ 784 -yscroll ".body.file.bar set" 785 } 786 bind .body.file.list <Button-1> {SelectList %W %y} 787 788 pack .body.file.list -side top -expand 1 -fill both 789 790 # time label and scale 791 frame .body.time -relief raised -bd 1 792 label .body.time.label -text "0:00 / 0:00" 793 pack .body.time.label -side top 794 scale .body.time.scale -orient horizontal -length 280\ 795 -from 0 -to 100 -tickinterval 10 796 bind .body.time.scale <ButtonRelease-1> {JumpCmd [%W get]} 797 pack .body.time.scale -side bottom -expand 1 -fill x 798 799 # text browser 800 frame .body.text -relief raised -bd 1 801 scrollbar .body.text.bar -relief sunken\ 802 -command ".body.text.buf yview" 803 pack .body.text.bar -side right -fill y 804 text .body.text.buf -width 36 -height 12 -relief sunken -bd 2\ 805 -wrap word -yscroll ".body.text.bar set" 806 bind .body.text.buf <Button-1> { } 807 bind .body.text.buf <Any-Key> { } 808 pack .body.text.buf -side top -expand 1 -fill both 809 button .body.text.clear -text "Clear"\ 810 -command ClearMsg 811 pack .body.text.clear -side bottom 812 813 # volume label and scale 814 frame .body.volume -relief raised -bd 1 815 label .body.volume.label -text "Volume:" 816 pack .body.volume.label -side top 817 scale .body.volume.scale -orient horizontal -length 280\ 818 -from 0 -to 200 -tickinterval 25\ 819 -showvalue true -label "Volume"\ 820 -command VolumeCmd 821 pack .body.volume.scale -side bottom -expand 1 -fill x 822 .body.volume.scale set $Config(CurVol) 823 824 # buttons 825 global bitmap_path 826 frame .body.button -relief raised -bd 1 827 pack .body.button -side top -expand 1 -fill x 828 button .body.button.play -bitmap "play" -command "PlayCmd" 829 button .body.button.stop -bitmap "stop" -command "StopCmd" 830 button .body.button.prev -bitmap "prev" -command "PrevCmd" 831 button .body.button.back -bitmap "back" -command "BackwardCmd" 832 button .body.button.fwrd -bitmap "fwrd" -command "ForwardCmd" 833 button .body.button.next -bitmap "next" -command "NextCmd" 834 button .body.button.pause -bitmap "pause" -command "PauseCmd" 835 button .body.button.quit -bitmap "quit" -command "QuitCmd" 836 pack .body.button.play .body.button.pause\ 837 .body.button.prev .body.button.back\ 838 .body.button.stop\ 839 .body.button.fwrd .body.button.next\ 840 .body.button.quit\ 841 -side left -ipadx 4 -pady 2 -fill x 842 843 if {$Config(Tracing)} { 844 # trace display 845 TraceCreate 846 } 847 TraceUpdate 848 849 # pack all items 850 DispTables 851 852 focus . 853 tk_menuBar .menu .menu.file .menu.mode .menu.disp 854 bind . <Key-Right> "ForwardCmd" 855 bind . <Key-n> "NextCmd" 856 bind . <Key-Left> "BackwardCmd" 857 bind . <Key-p> "PrevCmd" 858 bind . <Key-s> "PauseCmd" 859 bind . <Key-Down> "VolDownCmd" 860 bind . <Key-v> "VolDownCmd" 861 bind . <Key-Up> "VolUpCmd" 862 bind . <Key-V> "VolUpCmd" 863 bind . <Key-space> "PauseCmd" 864 bind . <Return> "PlayCmd" 865 bind . <Key-c> "StopCmd" 866 bind . <Key-q> "QuitCmd" 867 868 VolumeCmd $Config(CurVol) 1 869} 870