Jos Decoster Tchords is a script to find scales and chords on a guitar or bass. It looks like this:
The script can be found below.
If you play piano or keyboard, try KeyboardChords.
AMG: This is brilliant, thanks!!
## (This license blatantly stolen from Tktable and Tcl/Tk license and adapted - ## thus assume it falls under similar license terms). ## ## This software is copyrighted by Jos Decoster <jos _dot_ decoster _at_ gmail ## _dot_ com>. The following terms apply to all files associated with the ## software unless explicitly disclaimed in individual files. ## ## The authors hereby grant permission to use, copy, modify, distribute, and ## license this software and its documentation for any purpose, provided that ## existing copyright notices are retained in all copies and that this notice ## is included verbatim in any distributions. No written agreement, license, ## or royalty fee is required for any of the authorized uses. ## ## IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR ## DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT ## OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, ## EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## ## THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, ## INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS ## PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO ## OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR ## MODIFICATIONS. ## ## RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government ## is subject to the restrictions as set forth in subparagraph (c) (1) (ii) ## of the Rights in Technical Data and Computer Software Clause as DFARS ## 252.227-7013 and FAR 52.227-19. namespace eval ::Chords { variable all_notes variable scales variable chords variable chords_abbrev variable tunings variable mididev variable fret_dist 30 variable string_dist 30 variable note_rad 10 variable note_font {arial 12 bold} # 0 1 2 3 4 5 6 7 8 9 10 11 set all_notes_sharp [list "A" "A#" "B" "C" "C#" "D" "D#" "E" "F" "F#" "G" "G#"] set all_notes_flat [list "A" "Bb" "B" "C" "Db" "D" "Eb" "E" "F" "Gb" "G" "Ab"] set all_notes $all_notes_sharp set note_colors [list "red" "magenta" "green" "blue" "plum1" "purple" "goldenrod" "orange" "beige" "gray70" "cyan" "white"] # Scales based on 'First Scales Dictionary' by [email protected] (STEFANO GOTTARDELLI) as found on www.olga.net and # 'more exotic scales and modes' by [email protected] (Andy Perades) also found on www.olga.net set scales(all,chromatic) [list 0 1 2 3 4 5 6 7 8 9 10 11] set scales(key) [list 0] set scales(major) [list 0 2 4 5 7 9 11] set scales(ionian,major) [list 0 2 4 5 7 9 11] set scales(dorian) [list 0 2 3 5 7 9 10] set scales(phrygian,kurd,arabic) [list 0 1 3 5 7 8 10] set scales(lydian) [list 0 2 4 6 7 9 11] set scales(mixolydian) [list 0 2 4 5 7 9 10] set scales(aeolian,natural_minor,ancient_minor) [list 0 2 3 5 7 8 10] set scales(locrian) [list 0 1 3 5 6 8 10] set scales(melodic_minor,jazz_minor) [list 0 2 3 5 7 9 11] set scales(javanese) [list 0 1 3 5 7 9 10] set scales(lydian_augmented) [list 0 2 4 6 8 9 10] set scales(lydian_dominant,overtone) [list 0 2 4 6 7 9 10] set scales(hindu) [list 0 2 4 5 7 8 10] set scales(locrian_natural) [list 0 2 3 5 6 8 10] set scales(super_locrian,ravel) [list 0 1 3 4 6 8 10] set scales(harmonic_minor,mohammedan) [list 0 2 3 5 7 8 11] set scales(harmonic_major) [list 0 2 4 5 8 9 11] set scales(romanian) [list 0 2 3 6 7 9 10] set scales(phrygian_dominant,phrygian_major,balkan,jewish,spanish_gypsy) [list 0 1 4 5 7 8 10] set scales(lydian_sharp) [list 0 3 4 6 7 9 11] set scales(ultra_locrian) [list 0 1 3 4 6 8 9] set scales(double_harmonic_minor,byzantine,gypsy,east_indian_raga) [list 0 1 4 5 7 8 11] set scales(hungarian_minor,algerian) [list 0 2 3 6 7 8 11] set scales(oriental) [list 0 1 4 5 6 9 10] set scales(pentatonic_minor) [list 0 3 5 7 10] set scales(pentatonic_major,mongolian) [list 0 2 4 7 9] set scales(pentatonic_egyptian) [list 0 2 5 7 10] set scales(pentatonic_ritusen) [list 0 2 5 7 9] set scales(pentatonic_japanese) [list 0 1 5 7 8] set scales(pentatonic_chinese) [list 0 2 4 5 11] set scales(pentatonic_indian) [list 0 4 5 7 10] set scales(prometheus) [list 0 2 4 6 9 10] set scales(prometheus_neapolitam) [list 0 1 4 6 7 10] set scales(whole_tone) [list 0 2 4 6 8 10] set scales(diminished) [list 0 2 3 5 6 8 9 11] set scales(diminished_inverted) [list 0 1 3 4 6 7 9 10] set scales(augmented) [list 0 3 4 7 8 11] set scales(blues_major) [list 0 2 3 4 7 9] set scales(blues_minor) [list 0 3 5 6 7 10] set scales(blues_altered) [list 0 2 3 4 5 6 7 9 10] # Chords based on long_chord_dbase.txt from [email protected] (Ray # Voith) found on www.olga.net. set chords(major) [list 0 4 7] set chords(minor) [list 0 3 7] set chords(seventh) [list 0 4 7 10] set chords(minor_seventh) [list 0 3 7 10] set chords(major_seventh) [list 0 4 7 11] set chords(sixth) [list 0 4 7 9] set chords(minor_sixth) [list 0 3 7 9] set chords(augmented) [list 0 4 8] set chords(augmented_seventh) [list 0 4 8 10] set chords(diminished) [list 0 3 6] set chords(diminished_seventh) [list 0 3 6 9] set chords(seventh_flatted_fifth) [list 0 4 6 10] set chords(minor_seventh_flatted_fifth) [list 0 3 6 10] set chords(ninth) [list 0 4 7 10 2] set chords(minor_ninth) [list 0 3 7 10 2] set chords(major_ninth) [list 0 4 7 11 2] set chords(eleventh) [list 0 4 7 10 2 5] set chords(diminished_ninth) [list 0 4 7 10 1] set chords(added_ninth) [list 0 4 7 2] set chords(added_fourth) [list 0 4 7 5] set chords(suspended) [list 0 5 7] set chords(suspended_ninth) [list 0 2 7] set chords(seventh_suspended_fourth) [list 0 5 7 10] set chords(seventh_suspended_ninth) [list 0 2 7 10] set chords(fifth) [list 0 7] set chords_abbrev(major) [list ""] set chords_abbrev(minor) "m" set chords_abbrev(seventh) "7" set chords_abbrev(minor_seventh) "m7" set chords_abbrev(major_seventh) [list "maj7" "M7"] set chords_abbrev(sixth) "6" set chords_abbrev(minor_sixth) "m6" set chords_abbrev(augmented) "+" set chords_abbrev(augmented_seventh) "7+" set chords_abbrev(diminished) "dim" set chords_abbrev(diminished_seventh) [list "dim7" "o"] set chords_abbrev(seventh_flatted_fifth) "7(5b)" set chords_abbrev(minor_seventh_flatted_fifth) "m7(5b)" set chords_abbrev(ninth) "9" set chords_abbrev(minor_ninth) "m9" set chords_abbrev(major_ninth) [list "maj9" "M9"] set chords_abbrev(eleventh) "11" set chords_abbrev(diminished_ninth) "dim9" set chords_abbrev(added_ninth) [list "(9)" "(2)"] set chords_abbrev(added_fourth) [list "(4)" "(11)"] set chords_abbrev(suspended) [list "sus" "sus4"] set chords_abbrev(suspended_ninth) [list "sus9" "sus2"] set chords_abbrev(seventh_suspended_fourth) [list "7sus" "7sus4"] set chords_abbrev(seventh_suspended_ninth) [list "7sus2" "7sus9"] set chords_abbrev(fifth) [list "5" "(no 3rd)"] set tunings(standard) [list E A D G B E] set tunings(standard_bass) [list E A D G] set tunings(standard_5string_bass) [list B E A D G] set tunings(open_G) [list D G D G B D] set tunings(open_E) [list E B E G# B E] set tunings(open_D) [list D A D F# A D] set tunings(open_C) [list C G C G C E] set tunings(broken_D) [list D A D G B E] } proc ::Chords::get_notes { start positions } { variable all_notes set notes {} foreach lpos $positions { set pos [expr {($start + $lpos) % 12}] lappend notes [lindex $all_notes $pos] } return $notes } proc ::Chords::scale { key type } { variable all_notes variable scales set start [lsearch $all_notes $key] if { $start < 0 } { return -code error "Chords ERROR: unknown key '$key'" } if { ![info exists scales($type)] } { return -code error "Chords ERROR: unknown scale-type '$type'" } return [::Chords::get_notes $start $scales($type)] } proc ::Chords::chord { key type } { variable all_notes variable chords set start [lsearch $all_notes $key] if { $start < 0 } { return -code error "Chords ERROR: unknown key '$key'" } if { ![info exists chords($type)] } { return -code error "Chords ERROR: unknown scale-type '$type'" } return [::Chords::get_notes $start $chords($type)] } proc ::Chords::notes_to_string { base notes {frets 20} } { variable all_notes set pos [lsearch $all_notes $base] if { $pos < 0 } { return -code error "Chords ERROR: unknown base '$base'" } set string {} for { set i 0 } { $i <= $frets } { incr i } { set note [lindex $all_notes $pos] if { [lsearch $notes $note] >= 0 } { lappend string $note } else { lappend string {} } set pos [expr {($pos + 1) % 12}] } return $string } proc ::Chords::draw_guitar { cvs strings frets x y hstart vstart } { variable fret_dist variable string_dist variable note_font set nw [expr {$frets*$fret_dist + $fret_dist}] set nh [expr {[llength $strings]*$string_dist}] set ny0 $y set ny1 [expr {$ny0 + $nh}] switch -exact -- $hstart { l { set nx0 $x set nx1 [expr {$x + $nw}] set fret_incr $fret_dist } r { set nx0 [expr {$x + $nw}] set nx1 $x set fret_incr -$fret_dist } default { return -code error "Chords ERROR: unknown hstart '$hstart'" } } # Neck $cvs create rect $nx0 $ny0 $nx1 $ny1 -fill black -outline black -tags guitar # Frets set fx0 [expr {$nx0 + $fret_incr}] $cvs create line $fx0 $ny0 $fx0 $ny1 -width 8 -fill gray90 -tags guitar incr fx0 $fret_incr for { set i 0 } { $i < $frets } { incr i } { $cvs create line $fx0 $ny0 $fx0 $ny1 -width 2 -fill gray80 -tags guitar incr fx0 $fret_incr } # Fret numbers set tx0 [expr {$nx0 + $fret_incr}] set ty0 [expr {$ny1 + $string_dist / 2}] for { set i 0 } { $i <= $frets } { incr i } { $cvs create text $tx0 $ty0 -text $i -tags guitar -font $note_font incr tx0 $fret_incr } return } proc ::Chords::draw_string { cvs nr string strings frets hstart vstart x y } { variable fret_dist variable string_dist variable note_rad variable note_font variable all_notes variable note_colors set nh [expr {[llength $strings]*$string_dist}] set nw [expr {$frets*$fret_dist + $fret_dist}] switch -exact -- $vstart { t { set ny0 $y set ny1 [expr {$y + $nh}] set sy0 [expr {$ny0 + $string_dist / 2 + ([llength $strings] - $nr) * $string_dist}] } b { set ny0 $y set ny1 [expr {$y + $nh}] set sy0 [expr {$ny1 - $string_dist / 2 - ([llength $strings] - $nr) * $string_dist}] } default { return -code error "Chords ERROR: unknown vstart '$vstart'" } } switch -exact -- $hstart { l { set nx0 $x set nx1 [expr {$x + $nw}] set fret_incr $fret_dist } r { set nx0 [expr {$x + $nw}] set nx1 $x set fret_incr -$fret_dist } default { return -code error "Chords ERROR: unknown hstart '$hstart'" } } $cvs create line $nx0 $sy0 $nx1 $sy0 -width $nr -fill gray90 -tags guitar switch -exact -- $hstart { l { set nx0 [expr {$x + $fret_dist / 2 - $note_rad}] set nx1 [expr {$x + $fret_dist / 2 + $note_rad}] set tx0 [expr {$x + $fret_dist / 2}] } r { set nx0 [expr {$x + $nw - $fret_dist / 2 + $note_rad}] set nx1 [expr {$x + $nw - $fret_dist / 2 - $note_rad}] set tx0 [expr {$x + $nw - $fret_dist / 2}] } default { return -code error "Chords ERROR: unknown hstart '$hstart'" } } set ny0 [expr {$sy0 - $note_rad}] set ny1 [expr {$sy0 + $note_rad}] foreach note $string { if { [string length $note] } { set clr [lindex $note_colors [lsearch $all_notes $note]] $cvs create oval $nx0 $ny0 $nx1 $ny1 -fill $clr -tags guitar $cvs create text $tx0 $sy0 -text $note -anchor c -tags guitar -font $note_font } incr nx0 $fret_incr incr nx1 $fret_incr incr tx0 $fret_incr } return } proc ::Chords::draw_on_guitar { cvs notes {strings {E A D G B E}} {frets 20} {hstart l} {vstart t} {x 0} {y 0} } { ::Chords::draw_guitar $cvs $strings $frets $x $y $hstart $vstart set i [llength $strings] foreach string $strings { set nl [::Chords::notes_to_string $string $notes $frets] ::Chords::draw_string $cvs $i $nl $strings $frets $hstart $vstart $x $y incr i -1 } return } proc ::Chords::refresh_guitar_chord_selector { path {n1 ""} {n2 ""} {op ""} } { variable fret_dist variable string_dist variable all_notes variable all_notes_sharp variable all_notes_flat variable note_colors variable tunings variable chords_abbrev variable selected_canvas variable selected_key variable selected_cl variable selected_type variable selected_strings variable selected_frets variable ldisplayed_cl variable displayed_cl variable selected_nlf variable selected_tb variable selected_lr variable selected_shfl variable keypathlist # Delete old guitar drawing $selected_canvas($path) delete guitar $selected_canvas($path) configure -width [expr {$selected_frets($path) * $fret_dist + $fret_dist + 2*$string_dist}] -height [expr {[llength $tunings($selected_strings($path))] * $string_dist + 2*$string_dist }] # Set sharp / flat and adjust selected key set kidx [lsearch $all_notes $selected_key($path)] switch -exact -- $selected_shfl($path) { flat { set all_notes $all_notes_flat } sharp - default { set all_notes $all_notes_sharp } } set selected_key($path) [lindex $all_notes $kidx] foreach p $keypathlist($path) l $all_notes { $p configure -text $l -value $l } # Set chord / scale switch -exact -- $selected_cl($path) { chord { set stp [string first "," $selected_type($path)] if { $stp >= 0 } { set st [string range $selected_type($path) 0 [expr {$stp - 1}]] } else { set st $selected_type($path) } set notes [::Chords::chord $selected_key($path) $st] set ldisplayed_cl($path) "Displayed chord" set dc "$selected_key($path) $st" foreach abb $chords_abbrev($st) { append dc ", $selected_key($path)$abb" } set displayed_cl($path) $dc } scale { set notes [::Chords::scale $selected_key($path) $selected_type($path)] set ldisplayed_cl($path) "Displayed scale" set displayed_cl($path) [format "%s %s" $selected_key($path) $selected_type($path)] } default { set notes {} } } # Set bass string position switch -exact -- $selected_tb($path) { top { set tb t } bottom { set tb b } default { set tb t } } # Set head position switch -exact -- $selected_lr($path) { left { set lr l } right { set lr r } default { set lr l } } # Show notes below guitar drawing set nlf $selected_nlf($path) set sl [grid slaves $nlf] foreach s $sl { ::destroy $s } set i 0 foreach note $notes { if { [string length $note] } { set clr [lindex $note_colors [lsearch $all_notes $note]] label $nlf.nl$i -text $note -bg $clr -width 3 grid $nlf.nl$i -row 0 -column $i incr i } } # Draw guitar ::Chords::draw_on_guitar $selected_canvas($path) $notes $tunings($selected_strings($path)) $selected_frets($path) $lr $tb $string_dist $string_dist return } proc ::Chords::refresh_guitar_chord_scale_selector { path {n1 ""} {n2 ""} {op ""} } { variable scales variable chords variable chords_abbrev variable selected_btf variable selected_cl variable previous_cl variable selected_type variable typelistbox if { [string compare $previous_cl($path) $selected_cl($path)] } { switch -exact -- $selected_cl($path) { chord { set itypes [lsort [array names chords]] set types {} foreach type $itypes { set dc $type foreach abb $chords_abbrev($type) { if { [string length $abb] } { append dc ", $abb" } } lappend types $dc } } scale { set types [lsort [array names scales]] } default { set types None } } set previous_cl($path) $selected_cl($path) set lb $typelistbox($path) $lb delete 0 end eval $lb insert end $types $lb selection set [lsearch $types major] set selected_type($path) major } ::Chords::refresh_guitar_chord_selector $path return } proc ::Chords::start_guitar_chord_selector { path {strings standard} {frets 20} {key C} {type major} {cl scale} {bass top} {head left} {shfl sharp} } { variable all_notes variable scales variable chords variable tunings variable fret_dist variable string_dist variable selected_canvas variable selected_btf variable selected_nlf variable selected_key variable selected_type variable selected_strings variable selected_frets variable selected_cl variable selected_tb variable selected_lr variable selected_shfl variable previous_cl variable ldisplayed_cl variable displayed_cl variable typelistbox variable keypathlist set selected_key($path) $key set selected_type($path) $type set selected_cl($path) $cl set previous_cl($path) None set selected_strings($path) $strings set selected_frets($path) $frets set selected_tb($path) $bass set selected_lr($path) $head set selected_shfl($path) $shfl set bf [frame $path -bd 0 -relief flat] # Canvas set cf [frame $bf.cf -bd 5 -relief flat] pack $cf -fill both -expand true set cvs [canvas $cf.cvs -bd 0 -bg gray95 -width [expr {$frets * $fret_dist + $fret_dist}] -height [expr {[llength $strings] * $string_dist}]] pack $cvs -fill both -expand true set selected_canvas($path) $cvs # Notes list and scale or chord name set nlnf [frame $bf.nlnf -bd 5 -relief flat] pack $nlnf -fill x set nlf [frame $nlnf.nlf -bd 5 -relief flat] pack $nlf -fill x set selected_nlf($path) $nlf label $nlnf.disp -textvariable ::Chords::displayed_cl($path) -width 50 pack $nlnf.disp # entry $nlnf.mdisp -state disabled -textvariable ::Chords::midinotes($path) -width 50 # pack $nlnf.mdisp # Select buttons set btf [frame $bf.btf -bd 5 -relief flat] pack $btf -fill x set selected_btf($path) $btf # chord or scale and sharp or flat set scsff [frame $btf.scsff -bd 0] grid $scsff -row 0 -column 1 -sticky ewns ## chord or scale set scf [frame $scsff.scf -bd 2 -relief ridge] pack $scf -side top -fill both -expand true set whlbl [label $scf.whlbl -text "What" -relief raised] pack $whlbl -side top -fill x set cbs [radiobutton $scf.cbs -text Scales -variable ::Chords::selected_cl($path) -value scale -anchor w] set cbc [radiobutton $scf.cbc -text Chords -variable ::Chords::selected_cl($path) -value chord -anchor w] pack $cbs -side top -fill x pack $cbc -side top -fill x ## sharp or flat set sff [frame $scsff.sff -bd 2 -relief ridge] pack $sff -side top -fill both -expand true set sflbl [label $sff.sflbl -text "How" -relief raised] pack $sflbl -side top -fill x set cbsh [radiobutton $sff.cbsh -text Sharp -variable ::Chords::selected_shfl($path) -value sharp -anchor w] set cbfl [radiobutton $sff.cbfl -text Flat -variable ::Chords::selected_shfl($path) -value flat -anchor w] pack $cbsh -side top -fill x pack $cbfl -side top -fill x # key set kyf [frame $btf.keyf -bd 2 -relief ridge] grid $kyf -row 0 -column 2 -sticky ewns set kyf1 [frame $kyf.keyf1 -bd 0] pack $kyf1 -side top -fill x set kylbl [label $kyf1.kylbl -text "Key" -relief raised] pack $kylbl -side top -fill x set kyf2 [frame $kyf.keyf2 -bd 0] pack $kyf2 -fill both -expand true -side top set ka [radiobutton $kyf2.ka -text A -variable ::Chords::selected_key($path) -value A -anchor w] set kak [radiobutton $kyf2.kak -text A\# -variable ::Chords::selected_key($path) -value A\# -anchor w] set kb [radiobutton $kyf2.kb -text B -variable ::Chords::selected_key($path) -value B -anchor w] set kc [radiobutton $kyf2.kc -text C -variable ::Chords::selected_key($path) -value C -anchor w] set kck [radiobutton $kyf2.kck -text C\# -variable ::Chords::selected_key($path) -value C\# -anchor w] set kd [radiobutton $kyf2.kd -text D -variable ::Chords::selected_key($path) -value D -anchor w] set kdk [radiobutton $kyf2.kdk -text D\# -variable ::Chords::selected_key($path) -value D\# -anchor w] set ke [radiobutton $kyf2.ke -text E -variable ::Chords::selected_key($path) -value E -anchor w] set kf [radiobutton $kyf2.kf -text F -variable ::Chords::selected_key($path) -value F -anchor w] set kfk [radiobutton $kyf2.kfk -text F\# -variable ::Chords::selected_key($path) -value F\# -anchor w] set kg [radiobutton $kyf2.kg -text G -variable ::Chords::selected_key($path) -value G -anchor w] set kgk [radiobutton $kyf2.kgk -text G\# -variable ::Chords::selected_key($path) -value G\# -anchor w] set kl [label $kyf2.l] grid $ka -row 0 -column 0 -rowspan 2 -sticky w grid $kak -row 1 -column 1 -rowspan 2 -sticky w grid $kb -row 2 -column 0 -rowspan 2 -sticky w grid $kc -row 4 -column 0 -rowspan 2 -sticky w grid $kck -row 5 -column 1 -rowspan 2 -sticky w grid $kd -row 6 -column 0 -rowspan 2 -sticky w grid $kdk -row 7 -column 1 -rowspan 2 -sticky w grid $ke -row 8 -column 0 -rowspan 2 -sticky w grid $kf -row 10 -column 0 -rowspan 2 -sticky w grid $kfk -row 11 -column 1 -rowspan 2 -sticky w grid $kg -row 12 -column 0 -rowspan 2 -sticky w grid $kgk -row 13 -column 1 -rowspan 2 -sticky w grid $kl -row 14 -column 0 set keypathlist($path) [list $ka $kak $kb $kc $kck $kd $kdk $ke $kf $kfk $kg $kgk] # which chord or scale to display set typebf [frame $btf.typebf -bd 2 -relief ridge] grid $typebf -row 0 -column 3 -sticky ewns set typebfl [label $typebf.lbl -text "Type" -bd 2 -relief raised] pack $typebfl -side top -fill x set typef [frame $typebf.typef -bd 0] pack $typef -fill both -expand true set typelistbox($path) [listbox $typef.lb -xscrollcommand "$typef.scx set" -yscrollcommand "$typef.scy set" -selectmode single -width 35] scrollbar $typef.scx -command "$typef.lb xview" -width 11 -orient horizontal scrollbar $typef.scy -command "$typef.lb yview" -width 11 grid $typef.lb -row 0 -column 0 -sticky ewns grid $typef.scx -row 1 -column 0 -sticky ew grid $typef.scy -row 0 -column 1 -sticky ns grid rowconfigure $typef 0 -weight 1 grid rowconfigure $typef 1 -weight 0 grid columnconfigure $typef 0 -weight 1 grid columnconfigure $typef 1 -weight 0 bind $typef.lb <ButtonRelease-1> "::Chords::set_selected_type $path" # Tunings set strgf [frame $btf.strgf -bd 2 -relief ridge] grid $strgf -row 0 -column 4 -sticky ewns set strglbl [label $strgf.strglbl -text "Tuning" -relief raised] pack $strglbl -side top -fill x set cnt 1 foreach strgc [lsort -dictionary [array names tunings]] { set rb [radiobutton $strgf.strg$strgc -text $strgc -variable ::Chords::selected_strings($path) -value $strgc -anchor w] pack $rb -side top -fill x incr cnt } # number of frets set nff [frame $btf.nff -bd 2 -relief ridge] grid $nff -row 0 -column 6 -sticky ewns set nflbl [label $nff.nflbl -text "Frets" -relief raised] pack $nflbl -side top -fill x set cnt 0 foreach nfc {12 16 20 24 28} { set rb [radiobutton $nff.nf$nfc -text $nfc -variable ::Chords::selected_frets($path) -value $nfc -anchor w] pack $rb -side top -fill x incr cnt } # position of bass string and head set tblrf [frame $btf.tblrf -bd 0] grid $tblrf -row 0 -column 7 -sticky ewns ## position of bass string set tbf [frame $tblrf.tbf -bd 2 -relief ridge] pack $tbf -side top -expand true -fill both set tblbl [label $tbf.tblbl -text "Bass string" -relief raised] pack $tblbl -side top -fill x set cnt 1 foreach tbc {top bottom} { set rb [radiobutton $tbf.tb$tbc -text $tbc -variable ::Chords::selected_tb($path) -value $tbc -anchor w] pack $rb -side top -fill x incr cnt } ## position of head set lrf [frame $tblrf.lrf -bd 2 -relief ridge] pack $lrf -side top -expand true -fill both set lrlbl [label $lrf.lrlbl -text "Head" -relief raised] pack $lrlbl -side top -fill x set cnt 1 foreach lrc {left right} { set rb [radiobutton $lrf.lr$lrc -text $lrc -variable ::Chords::selected_lr($path) -value $lrc -anchor w] pack $rb -side top -fill x incr cnt } ::Chords::refresh_guitar_chord_scale_selector $path trace add variable ::Chords::selected_key($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_cl($path) write [list ::Chords::refresh_guitar_chord_scale_selector $path] trace add variable ::Chords::selected_type($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_strings($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_frets($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_tb($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_lr($path) write [list ::Chords::refresh_guitar_chord_selector $path] trace add variable ::Chords::selected_shfl($path) write [list ::Chords::refresh_guitar_chord_selector $path] return $bf } proc ::Chords::set_selected_type { path } { variable typelistbox variable selected_type set lb $typelistbox($path) set sl [$lb curselection] if { [llength $sl] == 0 } { return } set s [lindex $sl 0] set selected_type($path) [$lb get $s] puts "selected_type($path) = $selected_type($path)" } proc ::Chords::close_guitar_chord_selector { path } { variable selected_canvas variable selected_btf variable selected_nlf variable selected_key variable selected_type variable selected_strings variable selected_frets variable selected_cl variable selected_tb variable selected_lr variable selected_shfl variable previous_cl variable ldisplayed_cl variable displayed_cl variable typelistbox variable keypathlist unset selected_canvas($path) unset selected_btf($path) unset selected_nlf($path) unset selected_key($path) unset selected_type($path) unset selected_strings($path) unset selected_frets($path) unset selected_cl($path) unset selected_tb($path) unset selected_lr($path) unset selected_shfl($path) unset previous_cl($path) unset ldisplayed_cl($path) unset displayed_cl($path) unset typelistbox($path) unset keypathlist($path) destroy $path return } ::Chords::start_guitar_chord_selector .s pack .s -fill both -expand true