1#!/bin/sh 2# the next line restarts using wish \ 3exec wish8.4 "$0" "$@" 4 5package require -exact snack 2.2 6# Try to load optional file format handlers 7catch { package require snacksphere } 8catch { package require snackogg } 9 10# If they are present add new filetypes to file dialogs 11set extTypes {} 12set loadTypes {} 13set loadKeys {} 14set saveTypes {} 15set saveKeys {} 16if {[info exists snack::snacksphere]} { 17 lappend extTypes {SPHERE .sph} {SPHERE .wav} 18 lappend loadTypes {{SPHERE Files} {.sph}} {{SPHERE Files} {.wav}} 19 lappend loadKeys SPHERE SPHERE 20} 21if {[info exists snack::snackogg]} { 22 lappend extTypes {OGG .ogg} 23 lappend loadTypes {{Ogg Vorbis Files} {.ogg}} 24 lappend loadKeys OGG 25 lappend saveTypes {{Ogg Vorbis Files} {.ogg}} 26 lappend saveKeys OGG 27} 28snack::addExtTypes $extTypes 29snack::addLoadTypes $loadTypes $loadKeys 30snack::addSaveTypes $saveTypes $saveKeys 31 32 33snack::debug 0 34snack::sound s -debug 0 35snack::sound s2 36snack::sound sa 37 38set timestr "" 39option add *font {Helvetica 10 bold} 40wm title . "Play list" 41 42if 0 { 43set draw 1 44pack [frame .f] 45pack [canvas .f.c -width 140 -height 40] -side left 46pack [checkbutton .f.a -text Analyzer -variable draw] -side left 47 48for {set i 0} {$i<16} {incr i} { 49 .f.c create rect [expr 10*$i] 20 [expr 10*$i+10] 40 -fill green -outline "" 50 .f.c create rect [expr 10*$i] 10 [expr 10*$i+10] 20 -fill yellow -outline "" 51 .f.c create rect [expr 10*$i] 0 [expr 10*$i+10] 10 -fill red -outline "" 52 .f.c create rect [expr 10*$i] 0 [expr 10*$i+10] 40 -fill black -tag c$i 53} 54for {set i 0} {$i<17} {incr i} { 55 .f.c create line [expr 10*$i] 0 [expr 10*$i] 40 -width 5 56} 57for {set i 0} {$i<7} {incr i} { 58 .f.c create line 0 [expr 6*$i] 140 [expr 6*$i] -width 3 59} 60} 61 62pack [frame .frame] -side top -expand yes -fill both 63scrollbar .frame.scroll -command ".frame.list yview" 64listbox .frame.list -yscroll ".frame.scroll set" -setgrid 1 -selectmode single -exportselection false -height 16 65pack .frame.scroll -side right -fill y 66pack .frame.list -side left -expand 1 -fill both 67bind .frame.list <Double-ButtonPress-1> Play 68bind .frame.list <B1-Motion> {Drag %y} 69bind .frame.list <ButtonPress-1> {Select %y} 70bind . <BackSpace> Cut 71 72snack::createIcons 73pack [frame .panel] -side bottom -before .frame 74pack [button .panel.bp -bitmap snackPlay -command Play] -side left 75pack [button .panel.bs -bitmap snackStop -command Stop] -side left 76pack [button .panel.bo -image snackOpen -command Open] -side left 77set p 0 78pack [scale .panel.ss -show no -orient horiz -len 130 -var p] -side left 79set gain [snack::audio play_gain] 80pack [scale .panel.sv -show no -orient horiz -command {snack::audio play_gain}\ 81 -len 70 -var gain] -side left 82set setdrag 1 83bind .panel.ss <ButtonPress-1> {set setdrag 0} 84bind .panel.ss <ButtonRelease-1> {set setdrag 1 ; Play2} 85pack [label .panel.l -textvar timestr] 86 87proc Open {} { 88 global files 89 set file [snack::getOpenFile -format MP3] 90 if {$file != ""} { 91 set name [file tail $file] 92 set files($name) $file 93 .frame.list insert end $name 94 } 95} 96 97proc Play args { 98 global files t0 filelen 99 if {[.frame.list curselection] == ""} { 100 set i 0 101 } else { 102 set i [lindex [.frame.list curselection] 0] 103 } 104 .frame.list selection set $i 105 Stop 106 s config -file $files([.frame.list get $i]) 107 sa config -file $files([.frame.list get $i]) 108 if {$args == ""} { 109 s play -command Next 110 set t0 [clock scan now] 111 } else { 112 s play -start $args -command Next 113 set t0 [expr [clock scan now] - $args / [s cget -rate]] 114 } 115 set filelen [s length] 116 Timer 117} 118 119proc Play2 {} { 120 global filelen p 121 Play [expr int($p/100.0*[s length])] 122} 123 124proc Stop {} { 125 s stop 126 after cancel Timer 127} 128 129proc Timer {} { 130 global t0 timestr setdrag 131 set time [expr [clock scan now] - $t0] 132 set timestr [clock format $time -format "%M:%S"] 133 if $setdrag { 134 .panel.ss set [expr int(100 * $time / [s length -unit sec])] 135 } 136# Draw 137 after 100 Timer 138} 139 140sound beep 141set f [snack::filter generator 200 10000 0.0 triangle 1600] 142beep filter $f 143 144proc Next {} { 145 set i [lindex [.frame.list curselection] 0] 146 if {$i == ""} return 147 .frame.list selection clear $i 148 incr i 149 .frame.list selection set $i 150 .frame.list see $i 151 beep play 152 after 100 Play 153} 154 155set cut "" 156proc Cut {} { 157 global cut 158 if {[.frame.list curselection] != ""} { 159 set cut [.frame.list get [.frame.list curselection]] 160 .frame.list delete [.frame.list curselection] 161 } 162} 163 164proc Select y { 165 global old timestr files 166 set old [.frame.list nearest $y] 167 s2 config -file $files([.frame.list get $old]) 168 set timestr [clock format [expr int([s2 length -unit sec])] -format "%M:%S"] 169} 170 171proc Drag y { 172 global old 173 set new [.frame.list nearest $y] 174 if {$new == -1} return 175 set tmp [.frame.list get $old] 176 .frame.list delete $old 177 .frame.list insert $new $tmp 178 .frame.list selection set $new 179 set old $new 180} 181 182array set map { 183 0 2 184 1 3 185 2 4 186 3 5 187 4 7 188 5 9 189 6 12 190 7 15 191 8 19 192 9 23 193 10 28 194 11 34 195 12 41 196 13 49 197 14 56 198 15 63 199} 200 201proc Draw {} { 202 global draw 203 if ![snack::audio active] return 204 if {$draw == 1} { 205puts [time { 206 set pos [expr int([s cget -rate] * [snack::audio elapsed])] 207 if {$pos > 1000} { 208 set junk [sa sample [expr $pos - 1000]] 209 set junk [sa sample [expr $pos - 100]] 210 set junk [sa sample [expr $pos]] 211puts $junk 212 } 213 set spec [sa dBPower -start $pos -fftlen 128 -windowlength 128] 214 for {set i 0} {$i < 16} {incr i} { 215 set val [lindex $spec $::map($i)] 216 .f.c coords c$i [expr 10*($i-2)] 0 [expr 10*($i-2)+9] \ 217 [expr 100-1.4*($val+100)] 218 } 219 }] 220 } 221} 222 223if [info exists argv] { 224 if [file isdirectory $argv] { 225 catch {cd $argv} 226 } 227} 228 229wm protocol . WM_DELETE_WINDOW exit 230 231if {$::tcl_platform(platform) == "windows"} { 232 set filelist [glob -nocomplain *.mp3 *.wav] 233} else { 234 set filelist [glob -nocomplain *.mp3 *.wav *.MP3 *.WAV] 235} 236if {[info exists snack::snackogg]} { 237 set filelist [concat $filelist [glob -nocomplain *.ogg *.OGG]] 238} 239foreach file [lsort -dictionary $filelist] { 240 set name [file tail $file] 241 set files($name) $file 242 .frame.list insert end $file 243} 244