source colorwheel.tcl ;# from http://wiki.tcl.tk/12201
package require Tk
if {![catch {
package require midi
midi::openout 0
}]} {
proc beepLetter letter {
binary scan $letter c* ascii
foreach l $ascii {
midi::sendshort 144 $l 70
}
}
set lastColor 0
proc beepColor color {
variable lastColor
if {$color != $lastColor} {
scan $color "#%2x%2x%2x" r g b
midi::sendshort 144 [expr $r/2] 70
midi::sendshort 144 [expr $g/2] 70
midi::sendshort 144 [expr $b/2] 70
set lastColor $color
}
}
} else {
# Not nearly as interesting without the sound
proc beepLetter letter {}
proc beepColor args {}
}
package require Tk
proc centerCanvas {W h w} {
set h [expr {$h / 2.0}]
set w [expr {$w / 2.0}]
$W config -scrollregion [list -$w -$h $w $h]
}
proc createGui {toplevel} {
set parent $toplevel
if {$toplevel == "."} {set parent ""}
wm geometry $toplevel [join [wm maxsize .] x]+0+0
pack [canvas $parent.c] -expand 1
$parent.c configure -width [lindex [wm maxsize $toplevel] 0] -height [lindex [wm maxsize $toplevel] 1]
set c $parent.c
bind $c <Configure> {centerCanvas %W %h %w}
return $c
}
proc randomColor {} {
set r [expr int(rand()*255)]
set g [expr int(rand()*255)]
set b [expr int(rand()*255)]
return [format {#%02x%02x%02x} $r $g $b]
}
proc getLetter {a k} {
if {[string length $a] == 0} {
return $k
} else {
return $a
}
}
# Moves the letter to the given location and changes the color of the letter to the
# complement of the nearest color wheel pie wedge.
proc moveLetter {c x y} {
$c lower letter
set x [$c canvasx $x]; set y [$c canvasy $y]
set closest [$c find closest $x $y]
if {[string length $closest] > 0} {
set wedgeNum [lsearch -inline [$c gettags $closest] wedgenum*]
set wedgeNum [lindex [split $wedgeNum -] 1]
set complementNum [expr ($wedgeNum + 6) % 12]
$c itemconfigure letter -fill [$c itemcget wedgenum-$complementNum -fill]
}
$c raise letter
$c coords letter $x $y
}
# Create the canvas, color wheel, and letter
set canvas [createGui .]
displayRandomColorWheel $canvas
$canvas create text 100 100 -text a -font {{Times New Roman} 250} -tag letter
# As the mouse moves, the letter will follow
bind $canvas <Motion> [namespace code {moveLetter %W %x %y}]
# Play a set of musical notes when the letter is moved over a new color
bind $canvas <Motion> {+beepColor [%W itemcget [%W find closest %x %y] -fill]]}
# Display a letter or key symbol name upon any keypress
bind $canvas <Key> {%W itemconfigure letter -text [getLetter %A %K]}
# Map the letter to a musical note and play it
bind $canvas <Key> +[namespace code {beepLetter [getLetter %A %K]}]
# Mouse button changes the color
bind $canvas <Button> {%W itemconfigure letter -fill [randomColor]}
bind $canvas <Button> +[namespace code {
%W delete colorwheel
displayRandomColorWheel %W
%W lower colorwheel
}]
focus -force $canvasHello - what specific Tcl midi extension do you make use of here? Did you consider Snack as a possible extension alternative?Brian Theado - 17Aug04 - The library I used is referred to as midilib on the midi page. Snack could be used to either play a wav file for each note, or to play generated tones as done in tclmusic. Midi was easier to use and it sounds orders of magnitudes better (with my sound card's midi synthesizer and I would guess most sound cards?) than snack generated beeps. Writing code for the snack-generated beeps wouldn't be too hard--just use the inverse of the freqToNote function I added the other day to the tclmusic page and generate a beep at that frequency for a short period of time.

