#include <stdio.h>
#include <sys/types.h>
#include <libmidi.h>

/*
 * Send channel info to midi.
 * 'cmd' is one of:
 * 		CH_KEY_OFF 	key off (dx never sends this)
 * 		CH_KEY_ON	key on (used also for key off)
 * 		CH_CTL		control change
 * 		CH_P_BEND	pitch bend
 * 		CH_PRG		program change
 * 		CH_POLY_KPRS	polyphonic key pressure
 * 		CH_PRESSURE	channel pressure
 * 	chan -	channel to send it on, 0 - 15 (n == 0; ch1)
 * 	val1 -	first value, (0 - 127):
 * 		for CH_KEY_ON, CH_KEY_OFF:
 * 			key number:
 * 				for data from dx:
 * 					k == 36; C1 - k == 96; C6
 * 				for data to dx:
 * 					k == 0; C-2 - k == 127; G8
 * 		for CH_CTL, control number as follows for dx7:
 * 			DX7_CTL_MOD_WHEEL -	modulation wheel
 * 			DX7_CTL_BREATH - 	breath controler
 * 			DX7_CTL_AFTER -		after touch
 * 			DX7_CTL_FCONT -		foot controller
 * 			DX7_CTL_DE_KNOB -	data entry knob
 * 			DX7_CTL_SUST_FSW -	sostinuto foot switch
 * 			DX7_CTL_PORTA_FSW -	portamento foot switch
 * 			DX7_CTL_DE_PLUS -	data entry plus
 * 			DX7_CTL_DE_MINUS -	data entry minus
 * 		for CH_PRG:
 * 			0 - 127 
 * 			(for Yamaha dx7:  n == 0; v1 - n == 31; v32)
 * 		for CH_P_BEND
 * 			LS byte, 0 - 63
 * 			(for Yamaha: n == 64; at rest position)
 * 		for CH_POLY_KPRS
 * 			key number
 * 		for CH_PRESSURE
 * 			Channel pressure/after-touch amount, 0 - 127.
 * 			For Mono mode: channel (rather than key) is 
 * 			identified.
 * 	val2 -	next value 
 * 		for CH_KEY_OFF:
 * 			ignored
 * 		for CH_KEY_ON:
 * 			key velocity (Yamaha: v == 0; Key OFF, v == 1; 
 * 				ppp - v == 127; fff)
 * 		for CH_CTL:
 * 			control value, 0 - 127
 * 		for CH_PRG:
 * 			undefined
 * 		for CH_P_BEND:
 * 			MS byte, 64 - 127
 * 			(Yamaha: n == 64; at rest position)
 * 		for CH_POLY_KPRS
 * 			Pressure/After-touch value, 0 - 127.
 * 			Used in Omni mode. (Compare CH_PRESSURE in mono
 * 			mode.)
 * returns:
 * 	0 on success, -1 on failure
 * side effects:
 * 	writes data to synthesizer via midi_out()
 */
#define out(n, error) if (midi_out(f, n)==EOF) return MidiError(error), -1

send_ch(f, cmd, chan, val1, val2)
	u_char cmd, chan, val1, val2;
/*
** Write channel information to midi file descriptor 'f'.
** This includes all 'CH_...' macros (like key on/off, pitch bend, etc.)
** Return '0' if successful, '-1' if not.
*/
{
	switch (cmd) {
	case CH_KEY_ON:
	case CH_KEY_OFF:
	case CH_CTL:
	case CH_P_BEND:
	case CH_POLY_KPRS:
		out(cmd | (chan & M_CHAN_MASK), "midi_ch_1");
		out(val1 & M_VAL_MASK, "midi_ch_2");
		out(val2 & M_VAL_MASK, "midi_ch_3");
		break;
	case CH_PRG:
	case CH_PRESSURE:
		out(cmd | (chan & M_CHAN_MASK), "midi_ch_4");
		out(val1 & M_VAL_MASK, "midi_ch_5");
		break;
	default: return MidiError("midi_ch: invalid command=%x\n",cmd), -1;
	}
	return 0;
}
