#!avview_shell

set CARD 0

proc skip_args3 { a b c } {
}

proc get_value { value_list value_key } {
set i [lsearch -exact $value_list "$value_key"]
if { $i < 0 } {
	return "";
	}
incr i
return [lindex $value_list $i]
}

proc set_element_value { name values_count i j} {
global current_alsa_device
global debug
global $name.$i.v$j
if { $debug } {
	puts "changed $name value $j to [set $name.$i.v$j]"
	}
alsa_hctl_set_element_value "$current_alsa_device" $i $j [set $name.$i.v$j]
}

proc set_element_average_value { name values_count i} {
global current_alsa_device
global debug
global $name.$i.average_v
if { $debug } {
	puts "changed $name value all values to [set $name.$i.average_v]"
	}
for { set k 0 } { $k < $values_count } { incr k } {
	alsa_hctl_set_element_value "$current_alsa_device" $i $k [set $name.$i.average_v]
	}
}

proc average_list { list } {
set sum 0
foreach a $list {
	set sum [expr $sum + $a]
	}
return [expr $sum/[llength $list]]
}

proc set_locked_state { mw name element i } {
global $name.$i.locked
global current_alsa_device
global $name.$i.average_v
global debug
if { $debug } {
	puts "$name.$i.locked=[set $name.$i.locked]"
	}
set row [get_value [grid info $mw.label$i] "-row"]
if { [set $name.$i.locked] } {
	grid forget $mw.frame$i
	grid $mw.frame_locked$i -row $row -column 1 -sticky news
	set value [alsa_hctl_get_element_value "$current_alsa_device" $i]
	set $name.$i.average_v [average_list $value]
	} {
	grid forget $mw.frame_locked$i
	grid $mw.frame$i -row $row -column 1 -sticky news
	set values_count [get_value $element "-values_count"]
	for { set k 0 } { $k < $values_count } { incr k } {
		global $name.$i.v$k
		set $name.$i.v$k [set $name.$i.average_v]
		}
	}
}

proc generate_element_generic { mw i element name value } {
global $name.$i.locked element_color_index
trace vdelete $name.$i.locked w "set_locked_state $mw \"$name\" \"$element\" $i ; skip_args3"
if { ! [info exists $name.$i.locked] } {
	set $name.$i.locked 1
	}
eval label $mw.label$i -text "\"$name\"" -justify left [get_settings $mw.label$i ALSA $element_color_index]
destroy $mw.frame$i
destroy $mw.frame_locked$i
eval frame $mw.frame$i [get_settings $mw.frame$i ALSA $element_color_index]
eval frame $mw.frame_locked$i [get_settings $mw.frame_locked$i ALSA $element_color_index]
if { [llength $value] > 1 } {
	# check if all values are identical
	set a [lindex $value 0]
	set $name.$i.locked 1
	foreach aa $value {
		if { "$a" != "$aa" } {
			set $name.$i.locked 0
			}
		}

	eval checkbutton $mw.checkbutton$i -text "Locked" -variable \"$name.$i.locked\" \
			-indicatoron false [get_settings $mw.checkbutton$i ALSA $element_color_index]
	if { [set $name.$i.locked ] } {
		grid $mw.label$i $mw.frame_locked$i $mw.checkbutton$i -sticky news
		} {
		grid $mw.label$i $mw.frame$i $mw.checkbutton$i -sticky news
		}
	grid configure $mw.label$i -sticky news
	grid columnconfig $mw.frame$i 0 -weight 1
	} {
	grid $mw.label$i $mw.frame$i - -sticky news
	grid configure $mw.label$i -sticky news
	grid columnconfig $mw.frame$i 0 -weight 1
	}
trace variable $name.$i.locked w "set_locked_state $mw \"$name\" \"$element\" $i ; skip_args3"
}

proc generate_element { mw i element } {
global current_alsa_device
global element_color_index
if { [get_value $element "-interface"] != "MIXER" } {
		return
		}
set values_count [get_value $element "-values_count"]
set name [get_value $element "-name"]
grid columnconfig $mw 1 -weight 1
switch "[get_value $element "-type"]" \
	"BOOLEAN" {
		set value [alsa_hctl_get_element_value "$current_alsa_device" $i]
		eval label $mw.label$i -text "\"$name\"" -justify left [get_settings $mw.label$i ALSA $element_color_index]
		eval frame $mw.frame$i [get_settings $mw.frame$i ALSA $element_color_index]
		grid $mw.label$i $mw.frame$i - -sticky news
		grid configure $mw.label$i -sticky news
		for { set j 0 } { $j < $values_count } { incr j } {
			global $name.$i.v$j
			eval checkbutton $mw.frame$i.checkbutton$j -variable \"$name.$i.v$j\" [get_settings $mw.frame$i.checkbutton$j ALSA $element_color_index $j]
			grid $mw.frame$i.checkbutton$j -row 0 -column $j -sticky news
			trace vdelete $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			set $name.$i.v$j [lindex $value $j]
			trace variable $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			grid columnconfig $mw.frame$i $j -weight 1
			}			
		incr element_color_index
		} \
	"INTEGER" {
		set value [alsa_hctl_get_element_value "$current_alsa_device" $i]
		generate_element_generic $mw $i $element $name $value
		set min [get_value $element "-min"]
		set max [get_value $element "-max"]
		set step [get_value $element "-step"]
		if { "$step" == "0" } { set step 1 }
		for { set j 0 } { $j < $values_count } { incr j } {
			global $name.$i.v$j
			eval scale $mw.frame$i.scale$j -variable \"$name.$i.v$j\" \
				-from $min -to $max -resolution $step \
				-orient horizontal -showvalue false \
				[get_settings $mw.frame$i.scale$j ALSA $element_color_index $j]
			grid $mw.frame$i.scale$j -row $j -column 0 -sticky news
			trace vdelete $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			set $name.$i.v$j [lindex $value $j]
			trace variable $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			}
		global $name.$i.average_v
		eval scale $mw.frame_locked$i.scale -variable \"$name.$i.average_v\" \
			-from $min -to $max -resolution $step \
			-orient horizontal -showvalue false \
			[get_settings $mw.frame_locked$i.scale ALSA $element_color_index]
		grid $mw.frame_locked$i.scale -row $j -column 0 -sticky news
		trace vdelete $name.$i.average_v w "set_element_average_value \"$name\" $values_count $i; skip_args3"
		set $name.$i.average_v [average_list $value]
		trace variable $name.$i.average_v w "set_element_average_value \"$name\" $values_count $i; skip_args3"
		incr element_color_index
		} \
	"ENUMERATED" {
		eval label $mw.label$i -text "\"$name\"" -justify left [get_settings $mw.label$i ALSA $element_color_index]
		eval frame $mw.frame$i [get_settings $mw.frame$i ALSA $element_color_index]
		grid $mw.label$i $mw.frame$i - -sticky news
		grid configure $mw.label$i -sticky news
		set value [alsa_hctl_get_element_value "$current_alsa_device" $i]
		set min [get_value $element "-min"]
		set max [get_value $element "-max"]
		set step [get_value $element "-step"]
		if { "$step" == "0" } { set step 1 }
		grid columnconfig $mw.frame$i 0 -weight 1
		set items [get_value $element "-items"]
		for { set j 0 } { $j < $values_count } { incr j } {
			global $name.$i.v$j
			set "element.$i.$j.menu" [tk_optionMenu $mw.frame$i.optionmenu$j $name.$i.v$j none]
			eval $mw.frame$i.optionmenu$j configure [get_settings $mw.frame$i.optionmenu$j ALSA $element_color_index $j]
			eval [set "element.$i.$j.menu"] configure [get_settings [set "element.$i.$j.menu"] ALSA $element_color_index $j]
			[set element.$i.$j.menu] delete 0 end
			foreach item $items {
				[set element.$i.$j.menu] add radiobutton -label "$item" -value "$item" -variable $name.$i.v$j 
				}
			grid $mw.frame$i.optionmenu$j -row $j -column 0 -sticky news
			trace vdelete $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			set $name.$i.v$j [lindex $value $j]
			trace variable $name.$i.v$j w "set_element_value \"$name\" $values_count $i $j ; skip_args3"
			}
		incr element_color_index
		}
		
}

proc generate_mixer_window { canvas mw } {
global current_alsa_device
global current_alsa_info

if { ![winfo exists $mw] } {
	return
	}

foreach win [grid slaves $mw] { destroy $win }
if { "$current_alsa_device" == "none" } {
	canvas $mw.label -width 0 -height 0 -background red
	grid $mw.label
	$canvas configure -scrollregion "0 0 1 1"
	return
	}
eval label $mw.title -text "\"Mixer (ALSA)\"" \
	[get_settings $mw.title ALSA]
	
grid $mw.title - - -sticky news -pady 2 -padx 2
grid columnconfigure $mw 1 -weight 1
set i 0
global element_color_index
set element_color_index 0
foreach element $current_alsa_info {
	generate_element $mw $i $element
	incr i 
	}

update idletasks
set bbox [grid bbox $mw]
$canvas configure -scrollregion $bbox -width [expr [lindex $bbox 2]+8]
}
	
proc generate_alsa_window { cw } {
global alsa_window
global current_alsa_device
foreach win [grid slaves $cw] {
	destroy $win 
	}
destroy $cw.f.c.f

set cw_info [grid info $cw]
set master [get_value $cw_info "-in"]
set column [get_value $cw_info "-column"]
set row [get_value $cw_info "-row"]

if { !$alsa_window || ([alsa_present] == "no") } { 
	if { "$master" != "" } {
		grid columnconfigure $master $column -weight 0
		}
	canvas $cw.c -width 0 -height 0 -background red
	grid $cw.c
	return 
	}
if { "$master" != "" } {
	grid columnconfigure $master $column -weight 1
	grid rowconfigure $master [expr $row+1] -weight 1
	}

eval frame $cw.f [get_settings $cw.f ALSA]

label $cw.title -text "Audio (ALSA)" -background black -foreground white
eval $cw.title configure [get_settings $cw.title ALSA]
grid $cw.title - - -sticky news -pady 2 -padx 2 -row 0
grid columnconfigure $cw 1 -weight 1
label $cw.devicel -text "ALSA Audio device: "
eval $cw.devicel configure [get_settings $cw.devicel label ALSA]
global alsa_device_menu
global current_alsa_device1
set save_alsa_device $current_alsa_device1
trace vdelete current_alsa_device1 w "set_alsa_device .controlwin.alsamixer ; skip_args3"
set alsa_device_menu [tk_optionMenu $cw.device_optionmenu current_alsa_device1 none]
eval $cw.device_optionmenu configure [get_settings $cw.device_optionmenu ALSA]
eval $alsa_device_menu configure [get_settings $alsa_device_menu ALSA menu]
button $cw.rescan_button -text "Rescan" -command "rescan_alsa_devices $alsa_device_menu current_alsa_device1"
eval $cw.rescan_button configure [get_settings $cw.rescan_button ALSA]
grid $cw.devicel $cw.device_optionmenu $cw.rescan_button -sticky news
grid configure $cw.devicel -sticky nws

trace variable current_alsa_device1 w "set_alsa_device .controlwin.alsamixer ; skip_args3"

grid $cw.f - - -sticky news

after idle [subst -nocommands {
	global current_alsa_device 
	set current_alsa_device none 
	rescan_alsa_devices $alsa_device_menu current_alsa_device1
	global current_alsa_device1
	set current_alsa_device1 "$save_alsa_device"
	} ]

frame $cw.f1 -relief groove -borderwidth 2
eval $cw.f1 configure [get_settings $cw.f1 ALSA]

grid $cw.f1 - - -sticky news -padx 2 

set c_info [grid info $cw.f1]

grid rowconfig $cw [get_value $c_info "-row"] -weight 1

canvas $cw.f1.c -yscrollcommand "$cw.f1.vscroll set" -bd 0 -borderwidth 0\
	-highlightthickness 0 -confine "yes" -relief flat
scrollbar $cw.f1.vscroll -command "$cw.f1.c yview" -orient vertical 

eval $cw.f1.c configure [get_settings $cw.f1.c ALSA]
eval $cw.f1.vscroll configure [get_settings $cw.f1.vscroll ALSA]

#grid $cw.f1.c - $cw.f1.vscroll -sticky news
#grid rowconfig $cw.f1 0 -weight 1
#grid columnconfig $cw.f1 0 -weight 1

grid $cw.f1.vscroll $cw.f1.c -  -sticky news
grid rowconfig $cw.f1 0 -weight 1
grid columnconfig $cw.f1 1 -weight 1

#pack $cw.f1.c  $cw.f1.vscroll  -side right
#pack configure $cw.f1.c -fill both -expand yes
#pack configure $cw.f1.vscroll -fill y -expand yes 

eval frame $cw.f1.c.f [get_settings $cw.f1.c.f ALSA]
$cw.f1.c create window 5 0 -window $cw.f1.c.f -anchor nw
bind $cw.f1.c.f <Configure> "readjust_alsa_scrollbar $cw.f1.c %W %h"

if { "$current_alsa_device" != "none" } {
	generate_mixer_window $cw.f1.c $cw.f1.c.f	
	}

}
	
proc rescan_alsa_devices { alsa_device_menu variable} {
global $variable
set $variable none
$alsa_device_menu delete 0 end
$alsa_device_menu add radiobutton -label "none"\
				-value "none" -variable $variable
for {set i [alsa_card_next -1]} {$i >= 0 } { set i [alsa_card_next $i] } {
	set alsa_handle  "hw:CARD=$i"
	alsa_card_load $alsa_handle
	$alsa_device_menu add radiobutton -label "hw:CARD=$i [alsa_card_get_name $i]"\
				-value $alsa_handle -variable $variable
	}
}

proc set_alsa_device {cw} {
global current_alsa_device
global current_alsa_device1
global current_alsa_info
global alsa_window
if { $current_alsa_device != "none" } {
	alsa_hctl_close $current_alsa_device
	}
set current_alsa_device $current_alsa_device1
if { $current_alsa_device != "none" } {
	alsa_hctl_open $current_alsa_device
	set current_alsa_info [alsa_hctl_get_elements_info $current_alsa_device]
	}	
if { $alsa_window } {
	generate_mixer_window $cw.f1.c $cw.f1.c.f
	}
}

proc readjust_alsa_scrollbar {canvas frame height} {
    if {[$frame cget -height] != $height} {
	$canvas configure -scrollregion [grid bbox $frame]
	eval $frame configure -height $height
    }
}

global alsa_window
set alsa_window 0
global current_alsa_device
set current_alsa_device "none"

