/* GSI - general sound interface
 * Standard MIDI protocol/file format definitions.
 *
 * gsif_midi.h
 *
 * 1998 by W.H.Scholten
 *
 * This file is released to the public domain.
 */


#ifndef _GSI__gsif__gsif_midi_h
#define _GSI__gsif__gsif_midi_h

/* rename midi constants like this?:
 * MIDI__NOTE_OFF
 * MIDI__META_SEQUENCER_SPECIFIC, etc.
 */

/* MIDI status: */
#define MIDI_NOTE_OFF                0x80
#define MIDI_NOTE_ON                 0x90
#define MIDI_KEY_PRESSURE            0xA0 /* = aftertouch/note_pressure */
#define MIDI_CTL_CHANGE              0xB0
#define MIDI_PGM_CHANGE              0xC0
#define MIDI_CHN_PRESSURE            0xD0
#define MIDI_PITCH_BEND              0xE0
#define MIDI_SYSTEM_PREFIX           0xF0
/* undefined 0xF1 */
#define MIDI_SONG_POSITION           0xF2
#define MIDI_SONG_SELECT             0xF3
/* undefined 0xF4, F5 */
#define MIDI_TUNE_REQUEST            0xF6
#define MIDI_END_OF_SYSEX            0xF7

/* F8-FF: real time events: */

#define MIDI_META_EVENT              0xFF


/* midi controllers: */
#define MIDICTL_BANK_SELECT          0x00
#define MIDICTL_MODWHEEL             0x01
#define MIDICTL_BREATH               0x02
/* undefined  0x03 */
#define MIDICTL_FOOT                 0x04
#define MIDICTL_PORTAMENTO_TIME      0x05
#define MIDICTL_DATA_ENTRY           0x06
#define MIDICTL_MAIN_VOLUME          0x07
#define MIDICTL_BALANCE              0x08
/* undefined  0x09 */
#define MIDICTL_PAN                  0x0A
#define MIDICTL_EXPRESSION           0x0B
/* undefined  0x0C-0x1F */

/* controllers 0x20-0x3F are the same as 0x00-0x1F */

#define MIDICTL_DAMPER_PEDAL         0x40
#define MIDICTL_SUSTAIN              0x40 /* damper alias */
#define MIDICTL_HOLD                 0x40 /* damper alias */
#define MIDICTL_PORTAMENTO           0x41
#define MIDICTL_SOSTENUTO            0x42
#define MIDICTL_SOFT_PEDAL           0x43

#define MIDICTL_GENERAL_PURPOSE4     0x44

#define MIDICTL_HOLD2                0x45
/*  undefined  0x46 - 0x4F */

#define MIDICTL_GENERAL_PURPOSE5     0x50
#define MIDICTL_GENERAL_PURPOSE6     0x51
#define MIDICTL_GENERAL_PURPOSE7     0x52
#define MIDICTL_GENERAL_PURPOSE8     0x53

/*  undefined 0x54 - 0x5A */

#define MIDICTL_EXT_EFF_DEPTH        0x5B
#define MIDICTL_TREMOLO_DEPTH        0x5C
#define MIDICTL_CHORUS_DEPTH         0x5D
#define MIDICTL_DETUNE_DEPTH         0x5E
#define MIDICTL_CELESTE_DEPTH        0x5E /* detune alias */
#define MIDICTL_PHASER_DEPTH         0x5F
#define MIDICTL_DATA_INCREMENT       0x60
#define MIDICTL_DATA_DECREMENT       0x61
#define MIDICTL_NONREG_PARM_NUM_LSB  0x62
#define MIDICTL_NONREG_PARM_NUM_MSB  0x63
#define MIDICTL_REGIST_PARM_NUM_LSB  0x64
#define MIDICTL_REGIST_PARM_NUM_MSB  0x65

/*  undefined  0x66 - 0x77 */

#define MIDICTL_SOUNDS_OFF           0x78 /* rename MIDICTL_ALL_SOUNDS_OFF? */
#define MIDICTL_RESET_CONTROLLERS    0x79 /* rename MIDICTL_RESET_ALL_CONTROLLERS? */

#define MIDICTL_LOCAL_CONTROL        0x7A
#define MIDICTL_ALL_NOTES_OFF        0x7B
#define MIDICTL_OMNI_MODE_OFF        0x7C
#define MIDICTL_OMNI_MODE_ON         0x7D
#define MIDICTL_MONOPHONIC_MODE      0x7E
#define MIDICTL_POLYPHONIC_MODE      0x7F


/* midi meta events: */
#define MIDIMETA_SEQUENCE_NUMBER     0x00
#define MIDIMETA_TEXT                0x01
#define MIDIMETA_COPYRIGHT_NOTICE    0x02
#define MIDIMETA_SEQUENCE_NAME       0x03
#define MIDIMETA_INSTRUMENT_NAME     0x04
#define MIDIMETA_LYRIC               0x05
#define MIDIMETA_MARKER              0x06
#define MIDIMETA_CUE_POINT           0x07

#define MIDIMETA_CHANNEL_PREFIX      0x20
#define MIDIMETA_END_OF_TRACK        0x2F
#define MIDIMETA_SET_TEMPO           0x51
#define MIDIMETA_SMPTE_OFFSET        0x54
#define MIDIMETA_TIME_SIGNATURE      0x58
#define MIDIMETA_KEY_SIGNATURE       0x59
#define MIDIMETA_SEQUENCER_SPECIFIC  0x74


struct gsi_track_status {
	unsigned char *data;
	unsigned long data_length;/* length of track (bytes) */

	unsigned long index;      /* current position in data */
	unsigned int  ticks;      /* current midi tick count */
	unsigned char running;    /* running status (compresses midi's) */
};

struct gsi_song_status {
	int  midi_format;         /* already in the song struct but copied for
							   * convenience */
	/* rename to song_format? */

	int  ticks;               /* ticks of last midi event processed */
	int  last_ticks;          /* ticks of previous midi event (to see if we need to seq_wait()) */
	double time;              /* time (in seconds) of the last event processed
							   */
/*	double last_time;*/       /* time of the previous event seq_wait */
	int  last_synth_ticks;    /* synth-ticks of last seq_wait */
	double song_end_time;     /* the duration of the song (in seconds), -1 if
							   * not yet known. */

	int  midi_division;
	int  midi_tempo;

	int  reverb;
	int  chorus;
	int  percussion_chn;      /* MIDI default = 0x200 = channel 10 */

	int  tracks;              /* number of tracks in the song */
	struct gsi_track_status *track; /* 'tracks' structs with current status */
};

struct gsi_song_event {
	int  ticks;
	int  track;
	int  event;
	unsigned char *data;      /* pointer into track data */
	int  length;              /* length of the event in bytes */
};


#include <gsi/gsif.h> /* TEMP */

struct gsi_song_status *gsif_make_song_status (struct gsi_song *song);
void gsif_free_song_status (struct gsi_song_status *song);
void gsif_reset_song_status (struct gsi_song_status *status);

/* midi/hmp decoding functions: */
unsigned int  gsif_read_vl (int msb_midi_format, struct gsi_track_status *s);

int  gsif_next_midi_event (int max_ticks, struct gsi_song_status *status, int preferred_track, int start_ticks, struct gsi_song_event *event);
/* returns 0 normally, < 0 on error (GSIFMIDI_ERROR_TRACK_CORRUPT), > 0 when
 * there are no events left (GSIFMIDI_STATUS_NO_MORE_EVENTS,
 * GSIFMIDI_STATUS__NO_EVENTS_WITHIN_LIMIT)
 */

int  gsif_decode_sysex (struct gsi_song *song, struct gsi_song_status *song_status, struct gsi_song_event *event);


#endif /* _GSI__gsif__gsif_midi_h */
