#
# midi devices config
#
#devattach 0 "/dev/rmidi4" rw
#devattach 1 "/dev/rmidi3" rw

#
# set the current input channel
#
proc ci input {
	songsetcurinput $input
}

#
# set the current channel
#
proc cc chan {
	songsetcurchan $chan
}

#
# set the current filt
#
proc cf filt { 
	songsetcurfilt $filt
}

#
# set the current track
#
proc ct track { 
	songsetcurtrack $track
}

#
# create a channel and a filter
#
proc ni name chan {
	songsetcurtrack nil
	filtnew $name 
	channew $name $chan
	filtchanmap $name [songgetcurinput] $name
}

#
# create a new filter 
#
proc nf filt { 
	filtnew $filt
}

#
# create a new track 
#
proc nt name { 
	tracknew $name 
}

#
# some filter rules
#
proc ctldrop ic {
	filtctldrop [songgetcurfilt] [songgetcurinput] $ic
}
proc ctlmap ic oc {
	filtctlmap [songgetcurfilt] [songgetcurinput] [songgetcurchan] $ic $oc
}
proc transpose halftones {
	filtkeymap [songgetcurfilt] [songgetcurinput] [songgetcurchan] 0 127 $halftones
}

#
# do nothing, just echo trough the configuration of the current track
#
proc i  {
	songidle;
}

#
# play the song
#
proc p  {
	metroswitch 0
	songplay
}

#
# record a track while playing the song, start 1 measure before
# the current position
#
proc r  { 
	metroswitch 1
	songrecord
}

#
# print the list of tracks, channels and filters, etc
#
proc l  {
	songinfo
}

#
# change current position
#
proc g measure {
	songsetcurpos $measure
}

#
# change the current selection's length
#
proc sel length {
	songsetcurlen $length
}

#
# set note quantum
#
proc n denom {
	songsetcurquant [songgetunit]/$denom
} 

#
# quantise
#
proc q rate {
	trackquant [songgetcurtrack] [songgetcurpos] [songgetcurlen] $rate [songgetcurquant]
} 

#
# set the tempo factor
#
proc fac percent {
	songsetfactor $percent
}

#
# cut the given number of measures from the current 
# position on the current track
#
proc cut amount {	 
	trackcut [songgetcurtrack] [songgetcurpos] $amount [songgetcurquant]
}

#
# insert measures in a track, and select them
#
proc ins amount {
	trackinsert [songgetcurtrack] [songgetcurpos] $amount [songgetcurquant]
	songsetcurlen $amount
}

#
# clear a piece of a track
#
proc clr {
	trackblank [songgetcurtrack] [songgetcurpos] [songgetcurlen] [songgetcurquant] {}
}

#
# copy current selection 'where' measures forward
#
proc copy where {
	let track = [songgetcurtrack]
	let from = [songgetcurpos]
	let len = [songgetcurlen]
	trackcopy $track $from $len $track ($where + $from) [songgetcurquant] {}
}

#
# cut a piece of the song
#
proc gcut amount {
	let pos = [songgetcurpos] 
	let quant = [songgetcurquant]
	for i in [tracklist] {
		trackcut $i $pos $amount $quant
	}
}

#
# insert measures in the song
#
proc gins amount {
	let pos = [songgetcurpos] 
	let quant = [songgetcurquant]
	for i in [tracklist] {
		trackinsert $i $pos $amount $quant
	}
	songsetcurlen $amount
}

#
# copy a piece of the song 'where' measures forward
#
proc gcopy where {
	let from = [songgetcurpos]
	let amount = [songgetcurlen] 
	let quant = [songgetcurquant]
	for track in [tracklist] {
		trackcopy $track $from $amount $track ($where + $from) $quant {}
	}
}


#
# mute a track
#
proc mute track {
	tracksetmute $track 1
}

#
# unmute a track
#
proc unmute track {
	tracksetmute $track 0
}

#
# unmute all tracks
#
proc nomute {
	for i in [tracklist] {
		tracksetmute $i 0
	}
}

#
# mute all tracks but current
#
proc solo {
	let curtrack = [songgetcurtrack]
	for i in [tracklist] {
		tracksetmute $i ($i != $curtrack)
	}
}

#
# save the song
#
proc save filename {
	songsave $filename
}

#
# load a song
#
proc load filename {
	songload $filename
}

#
# export a song in a .mid
#
proc export filename {
	songexportsmf $filename
}

#
# import a song from a .mid
#
proc import filename {
	songimportsmf $filename
}

#
# change tempo a current position
#
proc tempo beat_per_measure {
	songsettempo [songgetcurpos] $beat_per_measure
}

#
# insert measures in the meta-track
#
proc timeins amount numerator denominator {
	songtimeins [songgetcurpos] $amount $numerator $denominator
}

#
# remove measures from the meta-track
#
proc timerm amount {
	songtimerm [songgetcurpos] $amount
}

#
# turn on general midi (send sysex)
#
proc gmon devnum {
	sendraw $devnum { 0xF0 0x7E 0x7F 0x09 0x01 0xF7 }
}

#
# configure an instrument for a given general midi patch
#
proc gmp patch {
	let chan = [songgetcurchan]
	chanconfev $chan { pc $chan ($patch - 1) }
}

#
# XV-2020 specific macros
#
# configures a instrument with the given bank/patch or bank rhythm
# bank 1,2,3,4 corresponds to preset A,B,C,D
# patches/rhythmes are counted from 1 to 128
#
proc xvp bank patch {
	let chan = [songgetcurchan]
	chanconfev $chan { xpc $chan ($patch - 1) (87 * 128 + (64 + $bank - 1)) }
}
proc xvr bank patch { 
	let chan = [songgetcurchan]
	chanconfev $chan { xpc $chan ($patch - 1) (86 * 128 + (64 + $bank - 1)) }
}

#
# generate a sysex message that set parameter on 
# address (a0,a1,a2,a3) to val
#
proc xvparam a0 a1 a2 a3 val {
	return {  							\
		0xf0 0x41 0x7f 0x00 0x10 0x12 $a0 $a1 $a2 $a3 $val	\
		128 - ($a0 + $a1 + $a2 + $a3 + $val) % 128		\
		0xf7 }
}

#
# controllers config
#
proc mod    v { let c = [songgetcurchan]; chanconfev $c {ctl $c 1  $v}; }
proc breath v { let c = [songgetcurchan]; chanconfev $c {ctl $c 2  $v}; }
proc vol    v { let c = [songgetcurchan]; chanconfev $c {ctl $c 7  $v}; }
proc bal    v { let c = [songgetcurchan]; chanconfev $c {ctl $c 8  $v}; }
proc pan    v { let c = [songgetcurchan]; chanconfev $c {ctl $c 10 $v}; }
proc reverb v { let c = [songgetcurchan]; chanconfev $c {ctl $c 91 $v}; }
proc chorus v { let c = [songgetcurchan]; chanconfev $c {ctl $c 93 $v}; }

#
# set RPN to the given value for the current chan
#
proc rpn addr val { 
	let c = [songgetcurchan]
	chanconfev $c {rpn $c $addr $val}
}


#
# set NRPN to the given value for the current chan
#
proc nrpn addr val { 
	let c = [songgetcurchan]
	chanconfev $c {nrpn $c $addr $val}
}
