if 0 {
  /*
    * This file is part of din.
    *
    * din is copyright (c) 2006 - 2018 Jagannathan Sampath <jag@dinisnoise.org>
    * For more information, please visit http://dinisnoise.org
    *
    *
  */
}

;# remove a value from a list
proc lremove {listVariable value} {
  upvar 1 $listVariable var
  set idx [lsearch -exact $var $value]
  set var [lreplace $var $idx $idx]
}

;# bring the math ops & functions to use them LISP style eg., + 2 3
namespace import ::tcl::mathop::*
namespace import ::tcl::mathfunc::*

;# console colors
set color(header) {set-text-color 1 0.75 0.5}
set color(text) {set-text-color 0.8 1 0.8}
set color(error) {set-text-color 1 0.6 0.6}
set color(fine) {set-text-color 0.6 1 0.6}

;# tap bpm
set resetbeat 0
proc tap-bpm-changed {name element op} {
  ;# tap bpm changed
  global taptarget tapbpm resetbeat
  set wr {}
  if $resetbeat {
    foreach i $taptarget {
      set-beat $i [get-beat $i first]
    }
    set wr {[+ reset]}
  }
  foreach tt $taptarget {
    set-bpm $tt $tapbpm
  }
}

trace add variable tapbpm write tap-bpm-changed

proc add-tap-target what {
  global taptarget
  lappend taptarget $what
}

proc remove-tap-target what {
  global taptarget
  lremove taptarget $what
}

;# list files in user directory matching extension
proc lsuserdir {{ext *} {orient h} } {
  global user
  set mapping [list .$ext {}]
  if {$orient eq "v" || $orient eq "vertical"} {lappend mapping { } \n}
  string map $mapping [lsort [glob -nocomplain -tails -directory $user *.$ext]]
}

proc bad-sub-command {c} {
  upvar $c cmds
  set err "bad sub-command. should be: "
  foreach i [lrange $cmds 0 end-1] {
    append err "$i, "
  }
  append err "or [lindex $cmds end]"
}

proc exec-sub-command {ucmds uactions ucmd uargs} {
  upvar $ucmds cmds $uactions actions $ucmd cmd $uargs args
  set j 0
  foreach i $cmds {
    if {$cmd eq $i} {
      return [{*}[lindex $actions $j] {*}$args]
    }
    incr j
  }
  bad-sub-command cmds
}

;# tuning command -> list, set and get available tunings
proc tuning {cmd args} { ;# tuning command
  set cmds {list set get}
  set actions {"lsuserdir tuning" "set-var tuning" "get-var tuning"}
  exec-sub-command cmds actions cmd args
}

;# called when drones are deleted
proc drones-deleted {args} {}

;# called once every din loop
proc loop {} {} ;# required

;# list-patches command
set lsp_body {{{v ""}} {
  lsuserdir patch.tcl $v
}}

eval "proc list-patches $lsp_body"
eval "proc lp $lsp_body"

;# load-patch command
set lop_body {{patch {quiet 0}} {
	src $patch.patch
  if [catch {src $patch.patch}] {
    set-text-color 1 0.5 0.5
    echo "bad patch: $patch"
  } else {
    set-text-color 0.5 1 0.5
    if {$quiet eq 0} {
			echo "loaded $patch"
    	echo "help $patch for more information"
		}
  }
}}

eval "proc load-patch $lop_body"
eval "proc lop $lop_body"

;# make interval note variables based on current tuning
src make-interval-note-vars

;# load help displayer
src help

if {0} {
  make empty midi procs
  if user wants diagnostics, they can load midimap patch
}

proc make-midi name {
  uplevel #0 "proc $name args {}"
}

foreach i {midi-start midi-clock midi-note-on midi-note-off midi-pitch-bend midi-program-change midi-cc} {
  make-midi $i
}

proc setup-editors {} {
  set instrument [get-var instrument]
  set eds [set instrument]_editors
  global $eds
  set ids [array get $eds]
  foreach {i j} $ids {set-curve-editor $j $i}
}

proc update-editor {name screen} {
  set instrument [get-var instrument]
  set eds [set instrument]_editors
  global $eds
  array set $eds [list $screen $name]
}

proc show-eval-notice {} {

	set-text-color 1 1 0.5
	echo "Thank you for evaluating DIN Is Noise!"
	set-text-color 1 0.5 0.5
	echo "This evaluation version has these limits:"
	echo "You cannot save recordings,"
	echo "You cannot use plugins on the curve editors,"
	echo "You can only create a 2x2 drone mesh,"
	echo "You cannot do microtonal range modulation and note change,"
	echo "You can create only 1 ball in the Mondrian instrument and"
	echo "You can create only 1 binaural drone pair on the Binaural Drones instrument."
	echo ""
	set-text-color 1 1 0.5
	echo "To remove these limits please buy a License."
	echo "This is a Lifetime License that offers free upgrades for life."
	echo "And you will not see this message."
	echo ""
	echo "Your license also helps support my independent research and work "
	echo "on DIN Is Noise."
	echo ""
	echo "Hope you enjoy using the program!"
	echo ""
  echo "Jagannathan Sampath <jag@dinisnoise.org>"

}

proc buy-license os {
  set oss {Windows Darwin Linux} ;# platforms
  set launchers {{cmd /c start} open xdg-open} ;# to open the installed web browser
  if {$os in $oss} {
    set i [lsearch -exact $oss $os]
    exec {*}[lindex $launchers $i] https://dinisnoise.org/buy/
  }
}

proc factory-reset {} {
  global user
  file mkdir $user/reset2factory
  echo {Please restart DIN Is Noise to use factory settings}
}

proc exit {} {}

proc get-val {min max amount} { ;# get interpolated value from min to max
  set amount [/ $amount 127.0]
  return [expr { (1 - $amount) * $min + $amount * $max }]
}

proc get-nums {start end {step 1}} {
	;# get numbers from start to end with step
	set nums {}
	set i $start
	set j $end
	while {$i <= $end} {
		lappend nums $i
		incr i $step
	}
	return $nums
}

proc rnd {a b} {
	;# return random number in range (a,b)
	set r01 [rand]
	set ba [- $b $a]
	set v [+ $a [* $r01 $ba]]
	return $v
}

proc eval-expression e { ;# evaluates a tcl expression (used by field ui control)
	set status [catch "uplevel expr {$e}" ret]
	if {$status} {return $e} else {return $ret}
}

proc stopped-recording {} {}

proc key* {args} {
	;# set key for all instruments
	foreach i {microtonal_keyboard keyboard_keyboard mondrian sounding_board} {
		key $i {*}$args
	}
}

;# make set-bpm helpers
set set_bpm_op_val { {what op value} { set-bpm $what [$op [get-bpm $what] $value] } }
proc set-bpm' {*}$set_bpm_op_val
proc sb' {*}$set_bpm_op_val
unset set_bpm_op_val

;# make set-var helpers
set set_var_op_val {{what op value} {set-var $what [$op [get-var $what] $value]}}
proc set-var' {*}$set_var_op_val
proc sv' {*}$set_var_op_val
unset set_var_op_val


proc uptime {{cons 1}} {
	;# print the uptime of DIN
	global timenow genesis
	set elapsed [- $timenow $genesis]
	set hours [/ $elapsed 3600.0]
	set ihours [expr int($hours)]
	set mins [expr ($hours - $ihours) * 60.0]
	set imins [expr int($mins)]
	set seconds [expr ($mins - $imins) * 60.0]
	set output "${ihours} hours ${imins} minutes [expr int($seconds)] seconds"
	if $cons {echo $output} else {return $output}
}

src binaural-drones; ;# for binaural drones
set genesis $timenow ;# for uptime
