SETMIDIEVENT(evm[i * 5 + 1], 0, ME_USER_TEMPER_ENTER,
SETMIDIEVENT(evm[i * 5 + 1], 0, ME_USER_TEMPER_ENTRY,
int parse_sysex_event_multi(uint8 *val, int32 len, MidiEvent *evm){    int num_events = 0;				/* Number of events added */    uint32 channel_tt;    int i, j;    static uint8 xg_reverb_type_msb = 0x01, xg_reverb_type_lsb = 0x00;    static uint8 xg_chorus_type_msb = 0x41, xg_chorus_type_lsb = 0x00;    if(current_file_info->mid == 0 || current_file_info->mid >= 0x7e)	current_file_info->mid = val[0];    /* First, check for the various XG Bulk Dump events */    /* val[7] is the starting value for the event type */    /* Effect 1 */    else if(len >= 10 &&       val[0] == 0x43 && /* Yamaha ID */       val[2] == 0x4C && /* XG Model ID */       val[5] == 0x02)   /* Effect 1 */    {	uint8 addhigh, addmid, addlow;		/* Addresses */	uint8 *body;				/* SysEx body */	uint8 p;				/* Channel part number [0..15] */	int ent;				/* Entry # of sub-event */	uint8 *body_end;			/* End of SysEx body */	addhigh = val[5];	addmid = val[6];	addlow = val[7];	body = val + 8;	p = val[6];	body_end = val + len-3;	for (ent = val[7]; body <= body_end; body++, ent++) {	    switch(ent) {		case 0x00:	/* Reverb Type MSB */		    xg_reverb_type_msb = *body;		    break;		case 0x01:	/* Reverb Type LSB */		    xg_reverb_type_lsb = *body;		    set_xg_reverb_type(xg_reverb_type_msb, xg_reverb_type_lsb);		    break;		case 0x20:	/* Chorus Type MSB */		    xg_chorus_type_msb = *body;		    break;		case 0x21:	/* Chorus Type LSB */		    xg_chorus_type_lsb = *body;		    set_xg_chorus_type(xg_chorus_type_msb, xg_chorus_type_lsb);		    break;		case 0x0C:	/* Reverb Return */		    reverb_status.level = *body;		    recompute_reverb_status();		    ctl->cmsg(CMSG_INFO,VERB_NOISY,"Reverb Level (%d)",*body);		    break;		case 0x2C:	/* Chorus Return */		    chorus_param.chorus_level = *body;		    recompute_chorus_status();		    ctl->cmsg(CMSG_INFO,VERB_NOISY,"Chorus Level (%d)",*body);		    break;		default:		    ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported XG Bulk Dump SysEx. (ADDR:%02X %02X %02X VAL:%02X)",val[5],val[6],val[7],ent);		    continue;		    break;	    }	}    }    /* Effect 2 (Insertion Effects) */    if(len >= 10 &&       val[0] == 0x43 && /* Yamaha ID */       val[2] == 0x4C && /* XG Model ID */       val[5] == 0x03)   /* Effect 2 (Insertion Effects) */    {	uint8 addhigh, addmid, addlow;		/* Addresses */	uint8 *body;				/* SysEx body */	uint8 p;				/* Channel part number [0..15] */	int ent;				/* Entry # of sub-event */	uint8 *body_end;			/* End of SysEx body */	addhigh = val[5];	addmid = val[6];	addlow = val[7];	body = val + 8;	p = val[6];	body_end = val + len-3;	for (ent = val[7]; body <= body_end; body++, ent++) {	    switch(ent) {		/* need to add in insertion effects code */		/* need to figure out how XG insertion effects map on to		   the GS insertion effects */		default:		    ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported XG Bulk Dump SysEx. (ADDR:%02X %02X %02X VAL:%02X)",val[5],val[6],val[7],ent);		    continue;		    break;	    }	}    }    /* XG Multi Part Data parameter change */    /* There are two ways to do this, neither of which match the XG spec... */    /* First method via Bulk Dump */    else if(len >= 10 &&       val[0] == 0x43 && /* Yamaha ID */       val[2] == 0x4C && /* XG Model ID */       (val[4] == 0x29 || val[4] == 0x3F) && /* Blocks 1 or 2 */       val[5] == 0x08)   /* Multi Part */    {	uint8 addhigh, addmid, addlow;		/* Addresses */	uint8 *body;				/* SysEx body */	uint8 p;				/* Channel part number [0..15] */	int ent;				/* Entry # of sub-event */	uint8 *body_end;			/* End of SysEx body */	addhigh = val[5];	addmid = val[6];	addlow = val[7];	body = val + 8;	p = val[6];	body_end = val + len-3;	for (ent = val[7]; body <= body_end; body++, ent++) {	    switch(ent) {		case 0x01:	/* bank select MSB */		    SETMIDIEVENT(evm[num_events], 0, ME_TONE_BANK_MSB, p, *body, 0);		    num_events++;		    break;		case 0x02:	/* bank select LSB */		    SETMIDIEVENT(evm[num_events], 0, ME_TONE_BANK_LSB, p, *body, 0);		    num_events++;		    break;		case 0x03:	/* program number */		    SETMIDIEVENT(evm[num_events], 0, ME_PROGRAM, p, *body, 0);		    num_events++;		    break;		case 0x04:	/* Rcv CHANNEL */			SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, p, *body, 0x65);		    break;		case 0x05:	/* mono/poly mode */		    if(*body == 0) {			channel[p].mono = 1;		    } else {			channel[p].mono = 0;		    }		    break;		case 0x08:	/* note shift ? */		    SETMIDIEVENT(evm[num_events], 0, ME_KEYSHIFT, p, *body, 0);		    num_events++;		    break;		case 0x0B:	/* volume */		    SETMIDIEVENT(evm[num_events], 0, ME_MAINVOLUME, p, *body, 0);		    num_events++;		    break;		case 0x0E:	/* pan */		    if(*body == 0) {			SETMIDIEVENT(evm[num_events], 0, ME_RANDOM_PAN, p, 0, 0);		    }		    else {			SETMIDIEVENT(evm[num_events], 0, ME_PAN, p, *body, 0);		    }		    num_events++;		    break;		case 0x12:	/* chorus send */		    SETMIDIEVENT(evm[num_events], 0, ME_CHORUS_EFFECT, p, *body, 0);		    num_events++;		    break;		case 0x13:	/* reverb send */		    SETMIDIEVENT(evm[num_events], 0, ME_REVERB_EFFECT, p, *body, 0);		    num_events++;		    break;		case 0x23:	/* bend pitch control */		    SETMIDIEVENT(evm[num_events], 0,ME_RPN_MSB,p,0,0);		    SETMIDIEVENT(evm[num_events+1], 0,ME_RPN_LSB,p,0,0);		    SETMIDIEVENT(evm[num_events+2], 0,ME_DATA_ENTRY_MSB,p,(*body - 0x40) & 0x7F,0);		    num_events += 3;		    break;		case 0x41:	/* scale tuning */		case 0x42:		case 0x43:		case 0x44:		case 0x45:		case 0x46:		case 0x47:		case 0x48:		case 0x49:		case 0x4a:		case 0x4b:		case 0x4c:		    SETMIDIEVENT(evm[0], 0, ME_SCALE_TUNING, p, ent - 0x41, *body - 64);		    num_events++;		    ctl->cmsg(CMSG_INFO, VERB_NOISY, "Scale Tuning %s (CH:%d %d cent)",			      note_name[ent - 0x41], p, *body - 64);		    break;		default:		    ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported XG Bulk Dump SysEx. (ADDR:%02X %02X %02X VAL:%02X)",val[5],val[6],ent,*body);		    continue;		    break;	    }	}    }    /* Second method: specify them one SYSEX event at a time... */    else if(len == 8 &&       val[0] == 0x43 && /* Yamaha ID */       val[2] == 0x4C) /* XG Model ID */     {		uint8 p;				/* Channel part number [0..15] */		int ent;				/* Entry # of sub-event */		p = val[4];		ent = val[5];		/* set reverb/chorus type on both MSB and LSB events */		/* this will give the "intended" result even if the events are		   sent in the wrong order */		if(val[3] == 0x01) {	/* Effect 1 */			switch(ent) {				case 0x00:	/* Reverb Type MSB */				  xg_reverb_type_msb = val[6];				  set_xg_reverb_type(xg_reverb_type_msb, xg_reverb_type_lsb);				  break;				case 0x01:	/* Reverb Type LSB */				  xg_reverb_type_lsb = val[6];				  set_xg_reverb_type(xg_reverb_type_msb, xg_reverb_type_lsb);				  break;				case 0x20:	/* Chorus Type MSB */				  xg_chorus_type_msb = val[6];				  set_xg_chorus_type(xg_chorus_type_msb, xg_chorus_type_lsb);				  break;				case 0x21:	/* Chorus Type LSB */				  xg_chorus_type_lsb = val[6];				  set_xg_chorus_type(xg_chorus_type_msb, xg_chorus_type_lsb);				  break;				case 0x0C:	/* Reverb Return */				  SETMIDIEVENT(evm[0], 0,ME_SYSEX_XG_LSB,p,val[6],0x00);				  num_events++;				  break;				case 0x2C:	/* Chorus Return */				  SETMIDIEVENT(evm[0], 0,ME_SYSEX_XG_LSB,p,val[6],0x01);				  num_events++;				  break;				default:				  break;			}		} else if(val[3] == 0x08) {	/* Multi Part Data parameter change */			switch(ent) {				case 0x01:	/* bank select MSB */				  SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_MSB, p, val[6], 0);				  num_events++;				  break;				case 0x02:	/* bank select LSB */				  SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_LSB, p, val[6], 0);				  num_events++;				  break;				case 0x03:	/* program number */				  SETMIDIEVENT(evm[0], 0, ME_PROGRAM, p, val[6], 0);				  num_events++;				  break;				case 0x04:	/* Rcv CHANNEL */				  SETMIDIEVENT(evm[num_events], 0, ME_SYSEX_XG_LSB, p, val[6], 0x65);				  num_events++;				  break;				case 0x05:	/* mono/poly mode */				  if(val[6] == 0) {SETMIDIEVENT(evm[0], 0, ME_MONO, p, val[6], 0);}				  else {SETMIDIEVENT(evm[0], 0, ME_POLY, p, val[6], 0);}				  num_events++;				  break;				case 0x08:	/* note shift ? */				  SETMIDIEVENT(evm[0], 0, ME_KEYSHIFT, p, val[6], 0);				  num_events++;				  break;				case 0x0B:	/* volume */				  SETMIDIEVENT(evm[0], 0, ME_MAINVOLUME, p, val[6], 0);				  num_events++;				  break;				case 0x0E:	/* pan */				  if(val[6] == 0) {					SETMIDIEVENT(evm[0], 0, ME_RANDOM_PAN, p, 0, 0);				  }				  else {					SETMIDIEVENT(evm[0], 0, ME_PAN, p, val[6], 0);				  }				  num_events++;				  break;				case 0x12:	/* chorus send */				  SETMIDIEVENT(evm[0], 0, ME_CHORUS_EFFECT, p, val[6], 0);				  num_events++;				  break;				case 0x13:	/* reverb send */				  SETMIDIEVENT(evm[0], 0, ME_REVERB_EFFECT, p, val[6], 0);				  num_events++;				  break;				case 0x23:	/* bend pitch control */				  SETMIDIEVENT(evm[0], 0,ME_RPN_MSB,p,0,0);				  SETMIDIEVENT(evm[1], 0,ME_RPN_LSB,p,0,0);				  SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,(val[6] - 0x40) & 0x7F,0);				  num_events += 3;				  break;				case 0x41:	/* scale tuning */				case 0x42:				case 0x43:				case 0x44:				case 0x45:				case 0x46:				case 0x47:				case 0x48:				case 0x49:				case 0x4a:				case 0x4b:				case 0x4c:					SETMIDIEVENT(evm[0],							0, ME_SCALE_TUNING, p, ent - 0x41, val[6] - 64);					num_events++;					ctl->cmsg(CMSG_INFO, VERB_NOISY,							"Scale Tuning %s (CH:%d %d cent)",							note_name[ent - 0x41], p, val[6] - 64);					break;				default:				  ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported XG SysEx. (ADDR:%02X %02X %02X VAL:%02X)",val[3],val[4],val[5],val[6]);				  break;			}		}    }    /* parsing GS System Exclusive Message... */	/* val[4] == Parameter Address(High)	   val[5] == Parameter Address(Middle)	   val[6] == Parameter Address(Low)	   val[7]... == Data...	   val[last] == Checksum(== 128 - (sum of addresses&data bytes % 128)) 	*/    else if(len >= 9 &&	   val[0] == 0x41 && /* Roland ID */       val[1] == 0x10 && /* Device ID */       val[2] == 0x42 && /* GS Model ID */       val[3] == 0x12) /* Data Set Command */    {		uint8 p, dp, udn, gslen, port = 0;		int i, addr, addr_h, addr_m, addr_l, checksum;		p = block_to_part(val[5], midi_port_number);		/* calculate checksum */		checksum = 0;		for(gslen = 9; gslen < len; gslen++)			if(val[gslen] == 0xF7)				break;		for(i=4;i<gslen-1;i++) {			checksum += val[i];		}		if(((128 - (checksum & 0x7F)) & 0x7F) != val[gslen-1]) {			ctl->cmsg(CMSG_INFO,VERB_NOISY,"GS SysEx: Checksum Error.");			return num_events;		}		/* drum channel */		dp = rhythm_part[(val[5] & 0xF0) >> 4];		/* calculate user drumset number */		udn = (val[5] & 0xF0) >> 4;		addr_h = val[4];		addr_m = val[5];		addr_l = val[6];		if(addr_h == 0x50) {	/* for double module mode */			port = 1;			p = block_to_part(val[5], port);			addr_h = 0x40;		} else if(addr_h == 0x51) {			port = 1;			p = block_to_part(val[5], port);			addr_h = 0x41;		}		addr = (((int32)addr_h)<<16 | ((int32)addr_m)<<8 | (int32)addr_l);		switch(addr_h) {		case 0x40:			if((addr & 0xFFF000) == 0x401000) {				switch(addr & 0xFF) {				case 0x00:					SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_MSB,p,val[7],0);					SETMIDIEVENT(evm[1], 0, ME_PROGRAM,p,val[8],0);					num_events += 2;					break;				case 0x02:	/* Rx. Channel */					if (val[7] == 0x10) {						SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,								block_to_part(val[5],								midi_port_number ^ port), 0x80, 0x45);					} else {						SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,								block_to_part(val[5],								midi_port_number ^ port),								MERGE_CHANNEL_PORT2(val[7],								midi_port_number ^ port), 0x45);					}					num_events++;					break;				case 0x13:					if(val[7] == 0) {SETMIDIEVENT(evm[0], 0, ME_MONO,p,val[7],0);}					else {SETMIDIEVENT(evm[0], 0, ME_POLY,p,val[7],0);}					num_events++;					break;				case 0x14:	/* Assign Mode */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x24);					num_events++;					break;				case 0x15:	/* Use for Rhythm Part */					if(val[7]) {						rhythm_part[val[7] - 1] = p;					}					break;				case 0x16:	/* Pitch Key Shift */					break;				case 0x17:	/* Pitch Offset Fine */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x26);					num_events++;					break;				case 0x19:					SETMIDIEVENT(evm[0], 0,ME_MAINVOLUME,p,val[7],0);					num_events++;					break;				case 0x1A:	/* Velocity Sense Depth */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x21);					num_events++;					break;				case 0x1B:	/* Velocity Sense Offset */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x22);					num_events++;					break;				case 0x1C:					if (val[7] == 0) {						SETMIDIEVENT(evm[0], 0, ME_RANDOM_PAN, p, 0, 0);					} else {						SETMIDIEVENT(evm[0], 0,ME_PAN,p,val[7],0);					}					num_events++;					break;				case 0x21:					SETMIDIEVENT(evm[0], 0,ME_CHORUS_EFFECT,p,val[7],0);					num_events++;					break;				case 0x22:					SETMIDIEVENT(evm[0], 0,ME_REVERB_EFFECT,p,val[7],0);					num_events++;					break;				case 0x2C:					SETMIDIEVENT(evm[0], 0,ME_CELESTE_EFFECT,p,val[7],0);					num_events++;					break;				case 0x2A:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x00,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x01,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					SETMIDIEVENT(evm[3], 0,ME_DATA_ENTRY_LSB,p,val[8],0);					num_events += 4;					break;				case 0x30:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x08,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x31:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x09,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x32:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x20,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x33:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x21,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x34:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x63,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x35:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x64,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x36:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x66,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x37:					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,p,0x01,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,p,0x0A,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,val[7],0);					num_events += 3;					break;				case 0x40:	/* Scale Tuning */					for (i = 0; i < 12; i++) {						SETMIDIEVENT(evm[i],								0, ME_SCALE_TUNING, p, i, val[i + 7] - 64);						ctl->cmsg(CMSG_INFO, VERB_NOISY,								"Scale Tuning %s (CH:%d %d cent)",								note_name[i], p, val[i + 7] - 64);					}					num_events += 12;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			} else if((addr & 0xFFF000) == 0x402000) {				switch(addr & 0xFF) {				case 0x10:	/* Bend Pitch Control */					SETMIDIEVENT(evm[0], 0,ME_RPN_MSB,p,0,0);					SETMIDIEVENT(evm[1], 0,ME_RPN_LSB,p,0,0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,p,(val[7] - 0x40) & 0x7F,0);					num_events += 3;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			} else if((addr & 0xFFFF00) == 0x400100) {				switch(addr & 0xFF) {				case 0x30:	/* Reverb Macro */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x05);					num_events++;					break;				case 0x31:	/* Reverb Character */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x06);					num_events++;					break;				case 0x32:	/* Reverb Pre-LPF */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x07);					num_events++;					break;				case 0x33:	/* Reverb Level */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x08);					num_events++;					break;				case 0x34:	/* Reverb Time */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x09);					num_events++;					break;				case 0x35:	/* Reverb Delay Feedback */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x0A);					num_events++;					break;				case 0x36:	/* Unknown Reverb Parameter */					break;				case 0x37:	/* Reverb Predelay Time */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x0C);					num_events++;					break;				case 0x38:	/* Chorus Macro */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x0D);					num_events++;					break;				case 0x39:	/* Chorus Pre-LPF */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x0E);					num_events++;					break;				case 0x3A:	/* Chorus Level */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x0F);					num_events++;					break;				case 0x3B:	/* Chorus Feedback */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x10);					num_events++;					break;				case 0x3C:	/* Chorus Delay */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x11);					num_events++;					break;				case 0x3D:	/* Chorus Rate */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x12);					num_events++;					break;				case 0x3E:	/* Chorus Depth */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x13);					num_events++;					break;				case 0x3F:	/* Chorus Send Level to Reverb */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x14);					num_events++;					break;				case 0x40:	/* Chorus Send Level to Delay */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x15);					num_events++;					break;				case 0x50:	/* Delay Macro */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x16);					num_events++;					break;				case 0x51:	/* Delay Pre-LPF */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x17);					num_events++;					break;				case 0x52:	/* Delay Time Center */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x18);					num_events++;					break;				case 0x53:	/* Delay Time Ratio Left */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x19);					num_events++;					break;				case 0x54:	/* Delay Time Ratio Right */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1A);					num_events++;					break;				case 0x55:	/* Delay Level Center */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1B);					num_events++;					break;				case 0x56:	/* Delay Level Left */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1C);					num_events++;					break;				case 0x57:	/* Delay Level Right */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1D);					num_events++;					break;				case 0x58:	/* Delay Level */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1E);					num_events++;					break;				case 0x59:	/* Delay Feedback */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x1F);					num_events++;					break;				case 0x5A:	/* Delay Send Level to Reverb */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x20);					num_events++;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			} else if((addr & 0xFFFF00) == 0x400200) {				switch(addr & 0xFF) {	/* EQ Parameter */				case 0x00:	/* EQ LOW FREQ */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x01);					num_events++;					break;				case 0x01:	/* EQ LOW GAIN */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x02);					num_events++;					break;				case 0x02:	/* EQ HIGH FREQ */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x03);					num_events++;					break;				case 0x03:	/* EQ HIGH GAIN */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x04);					num_events++;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			} else if((addr & 0xFFFF00) == 0x400300) {				switch(addr & 0xFF) {	/* Insertion Effect Parameter */				case 0x00:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x27);					SETMIDIEVENT(evm[1], 0,ME_SYSEX_GS_LSB,p,val[8],0x28);					num_events += 2;					break;				case 0x03:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x29);					num_events++;					break;				case 0x04:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2A);					num_events++;					break;				case 0x05:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2B);					num_events++;					break;				case 0x06:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2C);					num_events++;					break;				case 0x07:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2D);					num_events++;					break;				case 0x08:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2E);					num_events++;					break;				case 0x09:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x2F);					num_events++;					break;				case 0x0A:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x30);					num_events++;					break;				case 0x0B:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x31);					num_events++;					break;				case 0x0C:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x32);					num_events++;					break;				case 0x0D:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x33);					num_events++;					break;				case 0x0E:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x34);					num_events++;					break;				case 0x0F:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x35);					num_events++;					break;				case 0x10:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x36);					num_events++;					break;				case 0x11:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x37);					num_events++;					break;				case 0x12:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x38);					num_events++;					break;				case 0x13:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x39);					num_events++;					break;				case 0x14:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3A);					num_events++;					break;				case 0x15:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3B);					num_events++;					break;				case 0x16:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3C);					num_events++;					break;				case 0x17:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3D);					num_events++;					break;				case 0x18:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3E);					num_events++;					break;				case 0x19:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x3F);					num_events++;					break;				case 0x1B:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x40);					num_events++;					break;				case 0x1C:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x41);					num_events++;					break;				case 0x1D:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x42);					num_events++;					break;				case 0x1E:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x43);					num_events++;					break;				case 0x1F:					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x44);					num_events++;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			} else if((addr & 0xFFF000) == 0x404000) {				switch(addr & 0xFF) {				case 0x00:	/* TONE MAP NUMBER */					if(val[7] == 0) {						SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_LSB,p,channel[p].tone_map0_number,0);					} else {						SETMIDIEVENT(evm[0], 0, ME_TONE_BANK_LSB,p,val[7],0);					}					num_events++;					break;				case 0x01:	/* TONE MAP-0 NUMBER */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x25);					num_events++;					break;				case 0x20:	/* EQ ON/OFF */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x00);					num_events++;					break;				case 0x22:	/* EFX ON/OFF */					SETMIDIEVENT(evm[0], 0,ME_SYSEX_GS_LSB,p,val[7],0x23);					num_events++;					break;				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;				}			}			break;		case 0x41:			switch(addr & 0xF00) {			case 0x100:	/* Play Note */				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x18,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);				num_events += 3;				break;			case 0x200:				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1A,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);				num_events += 3;				break;			case 0x400:				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1C,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0x1);				num_events += 3;				break;			case 0x500:				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1D,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);				num_events += 3;				break;			case 0x600:				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1E,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);				num_events += 3;				break;			case 0x700:				ctl->cmsg(CMSG_INFO,VERB_NOISY,"Rx. Note Off (CH:%d NOTE:%d VAL:%d)",dp,val[6],val[7]);				if(channel[dp].drums[val[6]] == NULL) {play_midi_setup_drums(dp, val[6]);}				channel[dp].drums[val[6]]->rx_note_off = val[7];				break;			case 0x900:				SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1F,0);				SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);				SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);				num_events += 3;				break;			default:				ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);				break;			}			break;#if 0		case 0x20:	/* User Instrument */			switch(addr & 0xF00) {				case 0x000:	/* Source Map */					get_userinst(64+udn, val[6])->source_map = val[7];					break;				case 0x100:	/* Source Bank */					get_userinst(64+udn, val[6])->source_bank = val[7];					break;#if !defined(TIMIDITY_TOOLS)				case 0x200:	/* Source Prog */					get_userinst(64+udn, val[6])->source_prog = val[7];					break;#endif				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;			}			break;#endif		case 0x21:	/* User Drumset */			switch(addr & 0xF00) {				case 0x100:	/* Play Note */					get_userdrum(64+udn, val[6])->play_note = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x18,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0x1);					num_events += 3;					break;				case 0x200:	/* Level */					get_userdrum(64+udn, val[6])->level = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1A,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);					num_events += 3;					break;				case 0x300:	/* Assign Group */					get_userdrum(64+udn, val[6])->assign_group = val[7];					if(val[7] != 0) {recompute_userdrum_altassign(udn+64, val[7]);}					break;				case 0x400:	/* Panpot */					get_userdrum(64+udn, val[6])->pan = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1C,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);					num_events += 3;					break;				case 0x500:	/* Reverb Send Level */					get_userdrum(64+udn, val[6])->reverb_send_level = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1D,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);					num_events += 3;					break;				case 0x600:	/* Chorus Send Level */					get_userdrum(64+udn, val[6])->chorus_send_level = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1E,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);					num_events += 3;					break;				case 0x700:	/* Rx. Note Off */					get_userdrum(64+udn, val[6])->rx_note_off = val[7];					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Rx. Note Off (CH:%d NOTE:%d VAL:%d)",dp,val[6],val[7]);					if(channel[dp].drums[val[6]] == NULL) {play_midi_setup_drums(dp, val[6]);}					channel[dp].drums[val[6]]->rx_note_off = val[7];					break;				case 0x800:	/* Rx. Note On */					get_userdrum(64+udn, val[6])->rx_note_on = val[7];					break;				case 0x900:	/* Delay Send Level */					get_userdrum(64+udn, val[6])->delay_send_level = val[7];					SETMIDIEVENT(evm[0], 0,ME_NRPN_MSB,dp,0x1F,0);					SETMIDIEVENT(evm[1], 0,ME_NRPN_LSB,dp,val[6],0);					SETMIDIEVENT(evm[2], 0,ME_DATA_ENTRY_MSB,dp,val[7],0);					num_events += 3;					break;				case 0xA00:	/* Source Map */					get_userdrum(64+udn, val[6])->source_map = val[7];					break;				case 0xB00:	/* Source Prog */					get_userdrum(64+udn, val[6])->source_prog = val[7];					break;#if !defined(TIMIDITY_TOOLS)				case 0xC00:	/* Source Note */					get_userdrum(64+udn, val[6])->source_note = val[7];					break;#endif				default:					ctl->cmsg(CMSG_INFO,VERB_NOISY,"Unsupported GS SysEx. (ADDR:%02X %02X %02X VAL:%02X %02X)",addr_h,addr_m,addr_l,val[7],val[8]);					break;			}			break;		case 0x00:	/* System */			switch (addr & 0xfff0) {			case 0x0100:	/* Channel Msg Rx Port (A) */				SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,						block_to_part(addr & 0xf, 0), val[7], 0x46);				num_events++;				break;			case 0x0110:	/* Channel Msg Rx Port (B) */				SETMIDIEVENT(evm[0], 0, ME_SYSEX_GS_LSB,						block_to_part(addr & 0xf, 1), val[7], 0x46);				num_events++;				break;			default:				ctl->cmsg(CMSG_INFO,VERB_NOISY, "Unsupported GS SysEx. "						"(ADDR:%02X %02X %02X VAL:%02X %02X)",						addr_h, addr_m, addr_l, val[7], val[8]);				break;			}			break;		}    }	/* Non-RealTime / RealTime Universal SysEx messages	 * 0 0x7e(Non-RealTime) / 0x7f(RealTime)	 * 1 SysEx device ID.  Could be from 0x00 to 0x7f.	 *   0x7f means disregard device.	 * 2 Sub ID	 * ...	 * E 0xf7	 */	if (len > 4 && val[0] >= 0x7e)		switch (val[2]) {		case 0x01:	/* Sample Dump header */		case 0x02:	/* Sample Dump packet */		case 0x03:	/* Dump Request */		case 0x05:	/* Sample Dump extensions */		case 0x06:	/* Inquiry Message */		case 0x07:	/* File Dump */			break;		case 0x08:	/* MIDI Tuning Standard */			switch (val[3]) {			case 0x01:				SETMIDIEVENT(evm[0], 0, ME_BULK_TUNING_DUMP, 0, val[4], 0);				for (i = 0; i < 128; i++) {					SETMIDIEVENT(evm[i * 2 + 1], 0, ME_BULK_TUNING_DUMP,							1, i, val[i * 3 + 21]);					SETMIDIEVENT(evm[i * 2 + 2], 0, ME_BULK_TUNING_DUMP,							2, val[i * 3 + 22], val[i * 3 + 23]);				}				num_events += 257;				break;			case 0x02:				SETMIDIEVENT(evm[0], 0, ME_SINGLE_NOTE_TUNING,						0, val[4], 0);				for (i = 0; i < val[5]; i++) {					SETMIDIEVENT(evm[i * 2 + 1], 0, ME_SINGLE_NOTE_TUNING,							1, val[i * 4 + 6], val[i * 4 + 7]);					SETMIDIEVENT(evm[i * 2 + 2], 0, ME_SINGLE_NOTE_TUNING,							2, val[i * 4 + 8], val[i * 4 + 9]);				}				num_events += val[5] * 2 + 1;				break;			case 0x0b:				channel_tt = ((val[4] & 0x03) << 14 | val[5] << 7 | val[6])						<< ((val[4] >> 2) * 16);				if (val[1] == 0x7f) {					SETMIDIEVENT(evm[0], 0, ME_MASTER_TEMPER_TYPE,							0, val[7], (val[0] == 0x7f));					num_events++;				} else {					for (i = j = 0; i < MAX_CHANNELS; i++)						if (channel_tt & 1 << i) {							SETMIDIEVENT(evm[j], 0, ME_TEMPER_TYPE,									MERGE_CHANNEL_PORT(i),									val[7], (val[0] == 0x7f));							j++;						}					num_events += j;				}				break;			case 0x0c:				SETMIDIEVENT(evm[0], 0, ME_USER_TEMPER_ENTER,						0, val[4], val[21]);				for (i = 0; i < val[21]; i++) {					SETMIDIEVENT(evm[i * 5 + 1], 0, ME_USER_TEMPER_ENTER,							1, val[i * 10 + 22], val[i * 10 + 23]);					SETMIDIEVENT(evm[i * 5 + 2], 0, ME_USER_TEMPER_ENTER,							2, val[i * 10 + 24], val[i * 10 + 25]);					SETMIDIEVENT(evm[i * 5 + 3], 0, ME_USER_TEMPER_ENTER,							3, val[i * 10 + 26], val[i * 10 + 27]);					SETMIDIEVENT(evm[i * 5 + 4], 0, ME_USER_TEMPER_ENTER,							4, val[i * 10 + 28], val[i * 10 + 29]);					SETMIDIEVENT(evm[i * 5 + 5], 0, ME_USER_TEMPER_ENTER,							5, val[i * 10 + 30], val[i * 10 + 31]);				}				num_events += val[21] * 5 + 1;				break;			}			break;		case 0x09:	/* General MIDI Message */		case 0x7b:	/* End of File */		case 0x7c:	/* Handshaking Message: Wait */		case 0x7d:	/* Handshaking Message: Cancel */		case 0x7e:	/* Handshaking Message: NAK */		case 0x7f:	/* Handshaking Message: ACK */			break;		}    return(num_events);}