#ifndef MIDI_MIDI_H
#define MIDI_MIDI_H

#ifndef EXEC_LISTS_H
 #include <exec/lists.h>
#endif

#ifndef EXEC_PORTS_H
 #include <exec/ports.h>
#endif

/* midi.library structures & defines */

#define MIDINAME    "midi.library"
#define MIDIVERSION 1L


struct MSource {
    struct Node Node;
    struct Image *Image;
    struct MinList RPList;
    APTR UserData;		/* user data extension */
};

/* node types for Source */
#define NT_MSOURCE	0x20
#define NT_PERMMSOURCE	0x21

struct MDest {
    struct Node Node;
    struct Image *Image;
    struct MinList RPList;
    struct MsgPort *DestPort;
    APTR UserData;		/* user data extension */
};

/* node types for Dest */
#define NT_MDEST	0x22
#define NT_PERMMDEST	0x23


struct RIMatch {
    UBYTE count;	/* 0 for match all */
    UBYTE match[3];
};

struct MRouteInfo {
    UWORD MsgFlags;
    UWORD ChanFlags;
    BYTE  ChanOffset;
    BYTE  NoteOffset;
    struct RIMatch SysExMatch;
    struct RIMatch CtrlMatch;
};

/* Msg Flags for MRouteInfo structure and returned by MidiMsgType */

#define MMF_CHAN	0x00ff
#define MMF_NOTEOFF	0x0001
#define MMF_NOTEON	0x0002
#define MMF_POLYPRESS	0x0004
#define MMF_CTRL	0x0008
#define MMF_PROG	0x0010
#define MMF_CHANPRESS	0x0020
#define MMF_PITCHBEND	0x0040
#define MMF_MODE	0x0080

#define MMF_SYSCOM	0x0100
#define MMF_SYSRT	0x0200
#define MMF_SYSEX	0x0400

struct MRoutePtr {
    struct MinNode node;
    struct MRoute *Route;
};

struct MRoute {
    struct MSource *Source;
    struct MDest *Dest;
    struct MRoutePtr SRoutePtr, DRoutePtr;
    struct MRouteInfo RouteInfo;
};



/* MIDI message defines - based on IMA MIDI Spec 1.0 except where noted */

/* Status Bytes */

   /* Channel Voice Messages (1sssnnnn) */
#define MS_NOTEOFF    0x80
#define MS_NOTEON     0x90
#define MS_POLYPRESS  0xA0
#define MS_CTRL       0xB0
#define MS_MODE       0xB0
#define MS_PROG       0xC0
#define MS_CHANPRESS  0xD0
#define MS_PITCHBEND  0xE0

   /* System Common Messages */
#define MS_SYSEX      0xF0
#define MS_SONGPOS    0xF2
#define MS_SONGSELECT 0xF3
#define MS_TUNEREQ    0xF6
#define MS_EOX	      0xF7

   /* System Real Time Messages */
#define MS_CLOCK      0xF8
#define MS_START      0xFA
#define MS_CONTINUE   0xFB
#define MS_STOP       0xFC
#define MS_ACTVSENSE  0xFE
#define MS_RESET      0xFF


/* Standard Controllers (from MMA - 8-86)

   /* proportional MSB - 0-31, LSB - 32-63 */
#define MC_MODWHEEL  1
#define MC_BREATH    2
#define MC_FOOT      4
#define MC_PORTATIME 5
#define MC_DATAENTRY 6
#define MC_VOLUME    7
#define MC_BALANCE   8
#define MC_PAN	     10

   /* switches/pedals - either on(7F) or off(00) */
#define MC_SUSTAIN   64
#define MC_PORTA     65
#define MC_SUSTENUTO 66
#define MC_SOFTPEDAL 67
#define MC_HOLD2     69
#define MC_DATAINCR  96
#define MC_DATADECR  97

/* Channel Modes */

#define MM_LOCAL     122
#define MM_ALLOFF    123
#define MM_OMNIOFF   124
#define MM_OMNION    125
#define MM_MONO      126
#define MM_POLY      127


/* Sys/Ex ID numbers (from MMA as described in IMA bulletin) */

#define MID_SCI      0x01
#define MID_BIGBRIAR 0x02
#define MID_OCTAVEPLATEAU 0x03
#define MID_MOOG     0x04
#define MID_PASSPORT 0x05
#define MID_LEXICON  0x06

#define MID_OBERHEIM 0x10
#define MID_PAIA     0x11
#define MID_SIMMONS  0x12
#define MID_FAIRLIGHT 0x14

#define MID_BONTEMPI 0x20
#define MID_SIEL     0x21
#define MID_SYNTHAXE 0x23

#define MID_KAWAI    0x40
#define MID_ROLAND   0x41
#define MID_KORG     0x42
#define MID_YAMAHA   0x43

/* special Sys/Ex ID numbers: Non-Commercial, Non-Real Time, Real Time */
#define MID_NC	0x7d
#define MID_NRT 0x7e
#define MID_RT	0x7f


/* handy macros */

    /* pack high/low bytes of a word into midi format */
#define MIDI_HIBYTE(word) ( (word) >> 7 & 0x7f )
#define MIDI_LOBYTE(word) ( (word) & 0x7f )

    /* unpack 2 midi bytes into a word */
#define MIDI_WORD(hi,lo) ( (hi & 0x7f) << 7 | (lo & 0x7f) )


/* midi.library routine declarations */

struct MSource *CreateMSource(), *FindMSource();
struct MDest *CreateMDest(), *FindMDest();
struct MRoute *CreateMRoute(), *MRouteSource(), *MRouteDest(), *MRoutePublic();
UBYTE *GetMidiMsg();
BOOL PutMidiMsg();
ULONG MidiMsgLength(), MidiMsgType();

#endif
