#!/bin/bash
clear
echo "		  Utility to split a keyboard of Yamaha ARIUS YDP-142 or YDP-162"
echo "		  --------------------------------------------------------------"
echo "			     writen by Jeronym Klimes (www.klimes.us)"
echo "		Thanks God for the authors of midish, Krusader editor, Lubuntu, etc."
echo
# 
# I bought my children a new piano (you may guess its name), and therefore I had to write this script.
# I have two examples how it plays on my page. It is noway a perfect recording, but it may illustrate abilities of this script:
#Lullaby of birdland (mp3)
#Czech folk song - I am from Kutna Hora (mp3)
#This script packed (zip)
#
#
usage() {
	echo "Usage:" 
	echo "	$(basename $0) [-l lower instrument number = 9] [-u upper instrument number = 1]"
	echo "		[-s split note number = 52 (f; F2)] [-i interactive mode to select instruments]"
	echo "		[-o just switch local control on]"
	echo
	echo "Yamaha digital piano ARIUS has not a fuction split, so you may use this script to play" 
	echo "two instruments simultaneously at an lower and upper range of your keyboard."
	echo
	echo "Connect your PC to Yamaha ARIUS via USB cable and run this script at the command line."	
	echo "You may need to install small utilities as midish, zenity, aseqdump, usually by a command:"
	echo "		sudo apt-get install nameoftheutility"
	echo "You may easily adapt this script for other instruments. See hints inside the script."
	echo
	echo "Warning! This program switch off so called local control, so keys on the keyboard stop to play."
	echo "So after running this program, you have to switch local control yourself by pressing:"
	echo "		DEMO + VOICE + C6 (c'''') on your Arius keyboard"
	echo "You can similar way run this script with parametr -o to switch local control on later:"
	echo "		$(basename $0) -o"
	echo
	echo "You can break this script at any time. Just press CTRL+C on the PC keyboard."
	exit 2
	}

upperinstrument=1  	# the number of the default upper instrument
lowerinstrument=9  	# the number of the default lower instrument
split=52			# default split is f (F2)
devicename="ARIUS"
	# Edit this line if you want to use another musical instrument then ARIUS.
device=$(aseqdump -l | grep "$devicename" |  awk '{print $1}')
	
localon() {
	echo "Switching on local control"

	exec midish -b <<EOF 
	dnew 2 "$device" wo #output
	onew lower  {2 3}
	co lower
	print "switching local control on again"
	oaddev  {ctl lower 122 127}
	p
EOF
# This EOF must start at the first column without any leading or trailing spaces.
	exit
	}
	
bank() {
	case $1 in 
		# Yamaha ARIUS YDP-142 Preset Voice List
		#Name 						MSB 0-127) 	LSB (0-127)	Program Change # (1-128) hex MSB LSB	dec MSB LSB
		1)  name="GrandPiano 1"; 	msb="108"; 	lsb="0"; 	patch="1" ;              hML=3600;	    dML=13824;;
		2)  name="GrandPiano 2"; 	msb="108"; 	lsb="3"; 	patch="1" ;              hML=3603;	    dML=13827;;
		3)  name="GrandPiano 3"; 	msb="108"; 	lsb="2"; 	patch="2" ;              hML=3602;	    dML=13826;;
		4)  name="E.Piano 1   ";	msb="108"; 	lsb="0"; 	patch="6" ;              hML=3600;	    dML=13824;;
		5)  name="E.Piano 2   ";	msb="108"; 	lsb="0"; 	patch="5" ;              hML=3600;	    dML=13824;;
		6)  name="Harpsichord ";	msb="108"; 	lsb="0"; 	patch="7" ;              hML=3600;	    dML=13824;;
		7)  name="Vibraphone  ";	msb="108"; 	lsb="0"; 	patch="12";              hML=3600;	    dML=13824;;
		8)  name="Pipe Organ  ";	msb="108"; 	lsb="1"; 	patch="20";              hML=3601;	    dML=13825;;
		9)  name="Jazz Organ  ";	msb="108"; 	lsb="0"; 	patch="17";              hML=3600;	    dML=13824;;
		10) name="Strings     ";	msb="108"; 	lsb="0"; 	patch="49";              hML=3600;	    dML=13824;;
		# Take care! The byte is only 7 bits here, so 128 and not 256, therefore:
		# dML = msb*128 + lsb
		# See Yamaha ARIUS YDP-162 YDP-142 MIDI Reference
		esac
	
    if [ "$2" == "lower" ]; then 
		lname=$name
		lmsb=$msb
		llsb=$lsb
		lpatch=$(($patch-1))
		ldML=$((128*$msb+$lsb))
		lhML=$hML
	    fi
	    
    if [ "$2" == "upper" ]; then 
		uname=$name
		umsb=$msb
		ulsb=$lsb
		upatch=$(($patch-1))
		udML=$((128*$msb+$lsb))
		uhML=$hML
	    fi
	}
bank $upperinstrument upper #set the default instrument
bank $lowerinstrument lower #set the default instrument

selectinstruments () {
	options=(\
		"1"  "GrandPiano 1"\
		"2"  "GrandPiano 2"\
		"3"  "GrandPiano 3"\
		"4"  "E.Piano 1   "\
		"5"  "E.Piano 2   "\
		"6"  "Harpsichord "\
		"7"  "Vibraphone  "\
		"8"  "Pipe Organ  "\
		"9"  "Jazz Organ  "\
		"10" "Strings     "\
		)

	selection=$(zenity --height 400 --list "${options[@]}" --column="#" --column="name"\
		--text="Select an instrument for the upper range of the piano" --title="Upper instrument"\
		--print-column="1" --hide-header )
	if [ "${#selection}" == 3 ]; then
		selection=${selection:0:1}
		else
		selection=${selection:0:2}
		fi
	upperinstrument=$selection
	bank $upperinstrument upper 
	
	selection=$(zenity --height 400 --list "${options[@]}" --column="#" --column="name"\
		--text="Select an instrument for the lower range of the piano" --title="Lower instrument"\
		--print-column="1" --hide-header )
	if [ "${#selection}" == 3 ]; then
		selection=${selection:0:1}
		else
		selection=${selection:0:2}
		fi
	lowerinstrument=$selection
	bank $lowerinstrument lower

	selection=$(zenity --scale --text "Pick a split key! (default 52 (F2; f)" --min-value=1 --max-value=85 --value=52 --step 1 )
		if [[ $selection = *[[:digit:]]* ]]; then # is selection a number?
			split=$selection
			fi
	
	echo
	echo Next time you can run this combination directly by executing the command:
	echo "	$(basename $0) -l $lowerinstrument -u $upperinstrument -s $split"
	}

while getopts oihl:u:s: optname; do
	case "$optname" in
		u)
			bank $OPTARG upper;;
		l)  
			bank $OPTARG lower;;
		s)
			split=$OPTARG;;
		h)
			usage;;
		i)
			interactive=true;;	
		o)
			localon;;	
		esac
	done

if [ $interactive ]; then 
	selectinstruments 
	fi
	
echo
echo "Instruments' parameters"
echo "	uno=$upperinstrument uname=$uname umsb=$umsb ulsb=$ulsb upatch=$upatch uhML=$uhML udML=$udML"
echo "	lno=$lowerinstrument lname=$lname lmsb=$lmsb llsb=$llsb lpatch=$lpatch lhML=$uhML ldML=$ldML"
echo "	split=$split"
echo "	device=$device"
echo
if [ -z $device ]; then
	echo "The keyboard Yamaha ARIUS is not connected to your PC. Exiting..."
	echo
	exit
	fi
	
#This is main midish procedure. You can run it by yourself in an interactive mode by runing program rmidish	
exec midish -b <<EOF
dnew 1 "$device" ro #input
inew input {1 0}
ci input

dnew 2 "$device" wo #output - the same keyboard as output divided into two ranges
onew upper 	{2 2}
onew lower  {2 3}

co upper
print "setting upper range instrument - $uname"
oaddev {xpc upper $upatch $udML}
#Other possibilities:
# oaddev {xpc upper upatch (128*$umsb+$ulsb)}
# oaddev {pc upper upatch}

co lower
print "setting lower range instrument - $lname"
oaddev {xpc lower $lpatch $ldML}

print "switching off local control"
oaddev  {ctl lower 122 0}
fnew mysplit
fmap {any input} {any upper}
fmap {any input} {any lower}
print "setting split point - $split"
fmap {note input 0..$split}        {note lower 0..$split}       # split at F2 (f)
fmap {note input ($split+1)..127}  {note upper ($split+1)..127} # split at F2 (f)
cf mysplit
print " "
print "Press key s to stop simulation. (This does not work... :-((( You have to press CTRL+C)"
print " "
i

#Unfortunately the following script does not work because of CTRL+C
#cf lower
#co lower
#print "switching local control on again"
#ls
#oaddev {ctl lower 122 127}

print "This is the very end. "
print "Do not forget to switch local control on by yourself. Press:"
print "DEMO + VOICE + C6 (c'''') on your keyboard"
print "or run this script with parameter -o"
EOF
# This EOF must start at the first column without any leading or trailing spaces.