(***************************************************************************
  :Program.       Midi.def
  :Author.        Jürgen Zimmermann
  :Address.       Ringstraße 6, 6719 Altleiningen, West-Germany
  :Phone.         06356/1456
  :ShortCut.      [JnZ]
  :Support.       -
  :Version.       1.0
  :Date.          22. Febuary 1990
  :Copyright.     PD
  :Language.      MODULA-II
  :Translator.    M2Amiga 3.3d
  :Contents.      Eine Modula-2 Implementation für Bill Barton's
  :Contents.      "midi.library" von Fish 227, siehe auch "MidiSupport"!
  :Imports.       "midi.library" V2.0 im LIBS:-Ordner
  :Remark.        Ich würde mich sehr über Kontakt mit anderen M2Amiga-Usern
  :Remark.        und MIDI-Freaks freuen.
  :Usage.         Siehe Anleitung für die Midi-Library (anbei!)
****************************************************************************)
(* $M- *)
DEFINITION MODULE Midi{"midi.library",7};

(*  Definitions pertaining to MIDI are derived from MIDI 1.0 Detailed
    Specification v4.0 (published by the Internation MIDI Association)
    and is current as of June, 1988.

    v2.0 - 23-Oct-88 *)


FROM Exec      IMPORT UByte, Byte, List, Library, SignalSemaphore, MsgPortPtr,
                      MinList, Node, MinNode, Message, TaskPtr;

FROM Intuition IMPORT ImagePtr;

FROM SYSTEM    IMPORT ADDRESS, BPTR;


CONST midiName    = "midi.library";
      midiVersion = 7;


TYPE MidiBasePtr    = POINTER TO MidiBase;
     MTaskInfoPtr   = POINTER TO MTaskInfo;
     MNodeInfoPtr   = POINTER TO MNodeInfo;
     MSourcePtr     = POINTER TO MSource;
     MDestPtr       = POINTER TO MDest;
     RIMatchPtr     = POINTER TO RIMatch;
     MRouteInfoPtr  = POINTER TO MRouteInfo;
     MRoutePtr      = POINTER TO MRoute;
     MidiPacketPtr  = POINTER TO MidiPacket;
     MListSignalPtr = POINTER TO MListSignal;

(* Msg Flags for MRouteInfo structure and returned by MidiMsgType *)

     MMFFlags       = (NoteOn, NoteOff, PolyPress, Ctrl, Prog, ChanPress,
                       PitchBend, Mode, SysCom, SysRt, SysEx, mmf11, mmf12,
                       mmf13, mmf14, mmf15);
     MMFFlagSet     = SET OF MMFFlags;

(* MidiChannel-Flags, um nur bestimmte Midi-Kanäle anzusprechen *)
     MidiChannels   = (Ch01, Ch02, Ch03, Ch04, Ch05, Ch06, Ch07, Ch08,
                       Ch09, Ch10, Ch11, Ch12, Ch13, Ch14, Ch15, Ch16);
     MidiChannelSet = SET OF MidiChannels;

     RIMFlags       = (extBit1,extBit2,rim2,rim3,rim4,rim5,extId,reverse);
     RIMFlagSet     = SET OF RIMFlags;


CONST MMFChan      = MMFFlagSet{NoteOn..Mode};
      MMFAll       = MMFChan + MMFFlagSet{SysCom, SysRt, SysEx};

      AllChannels  = MidiChannelSet{Ch01..Ch16};

      RIMCountBits = RIMFlagSet{extBit1, extBit2};
        (* mask for # of match values (0 for match all) *)
      RIMExtId     = RIMFlagSet{extId};
        (* indicates all 3 bytes of match[] == one 3 byte manuf.
           id (not valid for CtrlMatch) *)
      RIMExclude   = RIMFlagSet{reverse};
        (* reverses logic of RIMatch so that all except those specified pass *)


      RIMMaxCount = 3;

   (* node types for Source *)
      NTMSource     = 20H;
      NTMResMSource = 21H;

   (* node types for Dest *)
      NTMDest       = 22H;
      NTResMDest    = 23H;

   (* user flags *)
      MLSFSource = 00000001H; (* causes signal when SourceList changes *)
      MLSFDest   = 00000002H; (* causes signal when DestList changes *)


TYPE MidiBase = RECORD
                   libnode       : Library;
                   SourceList    : List;
                   DestList      : List;
                   ListSemaphore : SignalSemaphore;
                      (* blocks Source/Dest list management *)
                   RouteSemaphore: SignalSemaphore;
                      (* blocks RPList management & msg routing *)
                   SegList       : LONGCARD;
                   SysBase       : ADDRESS;
                   DosBase       : ADDRESS;
                   SignalList    : MinList;
                      (* list of MListSignal's *)
                END;

     MTaskInfo = RECORD
                 (* set by caller *)
                    name      : ADDRESS;
                    Pri       : INTEGER;
                    Entry     : ADDRESS; (* Adresse des TaskCodes *)
                    Stack     : CARDINAL;

                    Sources   : CARDINAL;
                    SourceList: MNodeInfoPtr;
                    Dests     : CARDINAL;
                    DestList  :  MNodeInfoPtr;

                 (* set by midi.library *)
                    Semaphore : SignalSemaphore;	(* locks task *)
                    UsageCount: CARDINAL;		(* task's usage count *)
                    TaskPort  : MsgPortPtr;		(* task's MsgPort *)
                    Segment   : BPTR;			(* task's Segment *)
                 END;


     MNodeInfo = RECORD
                    name : ADDRESS;
                    image: ImagePtr;
                    node : ADDRESS;
                 END;


     MSource = RECORD
                  node          : Node;
                  image         : ImagePtr;
                  RPList        : MinList;
                  userData      : ADDRESS;	(* user data extension *)

               (* new stuff for v2.0 *)
                  RouteMsgFlags : MMFFlagSet;
                  RouteChanFlags: MidiChannelSet;

(*  RouteMsgFlags: mask of all route->MsgFlags for this MSource;
    RouteChanFlags: mask of all route->ChanFlags for this MSource *)

               END;


TYPE RIMatch = RECORD
                  flags: RIMFlagSet;
                  match: ARRAY[1..RIMMaxCount] OF UByte;
               END;



     MRouteInfo = RECORD
                     MsgFlags  : MMFFlagSet;
                     ChanFlags : MidiChannelSet;
                     ChanOffset: Byte;
                     NoteOffset: Byte;
                     SysExMatch: RIMatch;
                     CtrlMatch : RIMatch;

(* MsgFlags:  flags enabling message types defined below (MMF_) (msg filters);
   ChanFlags: incoming channel enable flags (LSB = chan 1, MSB = chan 16)
              (channel filters);
   ChanOffset: signed offset applied to channels (simple channelizing);
   NoteOffset: signed offset applied to note numbers (transposition);
   SysExMatch: Sys/Ex manufacturer id filtering;
   CtrlMatch: Controller number filtering *)
                  END;


     MDest = RECORD
                node            : Node;
                image           : ImagePtr;
                RPList          : MinList;
                DestPort        : MsgPortPtr;
                userData        : ADDRESS;(* user data extension *)

             (* new stuff for v2.0 *)
                DefaultRouteInfo: MRouteInfo;
                   (* used when Routing function doesn't supply a RouteInfo *)
             END;



TYPE MRoutePointer = RECORD (* alias MRoutePtr (C-Definition!) *)
                        node : MinNode;
                        Route: MRoutePtr;
                     END;


     MRoute = RECORD
                 Source   : MSourcePtr;
                 Dest     : MDestPtr;
                 SRoute   : MRoutePointer;
                 DRoute   : MRoutePointer; (* MRoutePtr (C-Definition!) *)
                 RouteInfo: MRouteInfo;
              END;




(* MIDI Packet (new for v2.0) *)

       MidiPacket = RECORD	    (* returned by GetMidiPacket() *)
                       ExecMsg : Message;
                       Type    : MMFFlagSet;
                       Length  : CARDINAL;
                       reserved: LONGCARD;
                       MidiMsg : ARRAY[1..4] OF UByte;

(* ExecMsg: ***;
   Type: MMF_ bit for this message (as returned by MidiMsgType());
   Length: length of msg in bytes (as returned by MidiMsgLength());
   reserved: reserved for future expansion;
   MidiMsg: actual MIDI message (real length of this array is Length,
            always at least this much memory allocated) *)

                    END;


(* Public List Change Signal *)

        MListSignal = RECORD
                         node   : MinNode;
                         SigTask: TaskPtr;	(* task to signal *)
                         SigBit : UByte;	(* signal bit to use *)
                         Flags  : UByte;        (* user flags *)
                      END;



(* MIDI message defininition *)

(* Status Bytes *)

    (* Channel Voice Messages (1sssnnnn) (OR with channel number) *)
CONST

 MSNOTEOFF   = 80H;
 MSNOTEON    = 90H;
 MSPOLYPRESS = 0A0H;
 MSCTRL      = 0B0H;
 MSMODE      = 0B0H;
 MSPROG      = 0C0H;
 MSCHANPRESS = 0D0H;
 MSPITCHBEND = 0E0H;

    (* System Common Messages (11110sss) *)
 MSSYSEX      = 0F0H;
 MSQTRFRAME   = 0F1H;
 MSSONGPOS    = 0F2H;
 MSSONGSELECT = 0F3H;
 MSTUNEREQ    = 0F6H;
 MSEOX	      = 0F7H;

    (* System Real Time Messages (11111sss) *)
 MSCLOCK     = 0F8H;
 MSSTART     = 0FAH;
 MSCONTINUE  = 0FBH;
 MSSTOP      = 0FCH;
 MSACTVSENSE = 0FEH;
 MSRESET     = 0FFH;

(* Miscellaneous *)

 MIDDLEC 	 = 60H;	 (* middle C note value *)
 DEFAULTVELOCITY = 64H;	 (* default Note On or Off velocity *)
 PITCHBENDCENTER = 2000H;(* pitch bend center position as a 14 bit word *)
 MCLKSPERQTR	 = 24H;	 (* MIDI clocks per qtr-note *)
 MCLKSPERSP	 = 6H;	 (* MIDI clocks per song position index *)
 MCCENTER	 = 64H;  (* center value for controllers like Pan and Balance *)


(* Standard Controllers *)

    (* continuous 14 bit - MSB: 0-1f, LSB: 20-3f *)
 MCMODWHEEL   = 01H;
 MCBREATH     = 02H;
 MCFOOT       = 04H;
 MCPORTATIME  = 05H;
 MCDATAENTRY  = 06H;
 MCVOLUME     = 07H;
 MCBALANCE    = 08H;
 MCPAN        = 0AH;
 MCEXPRESSION = 0BH;
 MCGENERAL1   = 10H;
 MCGENERAL2   = 11H;
 MCGENERAL3   = 12H;
 MCGENERAL4   = 13H;

   (* continuous 7 bit (switches: 0-3f=off, 40-7f=on) *)
 MCSUSTAIN      = 40H;
 MCPORTA        = 41H;
 MCSUSTENUTO    = 42H;
 MCSOFTPEDAL    = 43H;
 MCHOLD2        = 45H;
 MCGENERAL5     = 50H;
 MCGENERAL6     = 51H;
 MCGENERAL7     = 52H;
 MCGENERAL8     = 53H;
 MCEXTDEPTH     = 5BH;
 MCTREMOLODEPTH = 5CH;
 MCCHORUSDEPTH  = 5DH;
 MCCELESTEDEPTH = 5EH;
 MCPHASERDEPTH  = 5FH;
 MCDATAINCR     = 60H;
 MCDATADECR     = 61H;
 MCNRPNL        = 62H;
 MCNRPNH        = 63H;
 MCRPNL         = 64H;
 MCRPNH         = 65H;

 MCMAX	        = 78H;	(* max controller value *)


(* Channel Modes *)

 MMMIN	      = 79H;	(* min mode value *)

 MMRESETCTRL  = 79H;
 MMLOCAL      = 7AH;
 MMALLOFF     = 7BH;
 MMOMNIOFF    = 7CH;
 MMOMNION     = 7DH;
 MMMONO       = 7EH;
 MMPOLY       = 7FH;


(* Registered Parameter Numbers *)
(*
    These are 16 bit values that need to be separated into two bytes for
    use with the MC_RPNH & MC_RPNL messages using 8 bit math (hi = MRP_
    >> 8, lo = MRP_ &   ff) as opposed to 7 bit math.  This is done
    so that the defines match the numbers from the MMA.  See MIDI 1.0
    Detailed Spec v4.0 pp 12, 23 for more info.
*)

 MRPPBSENS     = 0000H;
 MRPFINETUNE   = 0001H;
 MRPCOURSETUNE = 0002H;


(* MTC Quarter Frame messages *)
(*
    Qtr Frame message is F1 0nnndddd where

	nnn is a message type defined below
	dddd is 4 bit data nibble for those message types

    Each pair of nibbles is combined by the receiver into a single byte.
    There are masks and type values defined for some of these data bytes
    below.
*)

    (* message types *)
 MTCQFRAMEL = 00H;
 MTCQFRAMEH = 10H;
 MTCQSECL   = 20H;
 MTCQSECH   = 30H;
 MTCQMINL   = 40H;
 MTCQMINH   = 50H;
 MTCQHOURL  = 60H;
 MTCQHOURH  = 70H;	(* also contains time code type *)

    (* message masks *)
 MTCQTYPEMASK = 70H;	(* mask for type bits in message *)
 MTCQDATAMASK = 0FH;	(* mask for data bits in message *)

    (* hour byte *)
 MTCHTYPEMASK = 60H;	(* mask for time code type *)
 MTCHHOURMASK = 1FH;	(* hours mask (range 0-23) *)

    (* time code type values for hour byte *)
 MTCT24FPS        = 00H;
 MTCT25FPS        = 20H;
 MTCT30FPSDROP    = 40H;
 MTCT30FPSNONDROP = 60H;




(* Sys/Ex ID numbers *)

(* Now includes 3 byte extension for the American Group.  This new
   format uses a $00 as the sys/ex id followed by two additional bytes
   that actually identify the manufacturer.  These new extended id
   constants are 32 bit values (24 significant bits) that you will have
   to break apart manually.

   You can match or filter off one of the extended id's when using the
   RIMF_EXTID bit described above. *)

    (* American Group *)
XAMERICA      = 00H;
SEQUENTIAL    = 01H;
IDP           = 02H;
OCTAVEPLATEAU = 03H;
MOOG          = 04H;
PASSPORT      = 05H;
LEXICON       = 06H;
KURZWEIL      = 07H;
FENDER        = 08H;
AKG           = 0AH;
VOYCE         = 0BH;
WAVEFRAME     = 0CH;
ADA           = 0DH;
GARFIELD      = 0EH;
ENSONIQ       = 0FH;
OBERHEIM      = 10H;
APPLE         = 11H;
GREYMATTER    = 12H;
PALMTREE      = 14H;
JLCOOPER      = 15H;
LOWREY        = 16H;
ADAMSSMITH    = 17H;
EMU           = 18H;
HARMONY       = 19H;
ART           = 1AH;
BALDWIN       = 1BH;
EVENTIDE      = 1CH;
INVENTRONICS  = 1DH;
CLARITY       = 1FH;

   (* American Group extened *)
DIGITALMUSIC  = 0000007H;
IOTA          = 0000008H;
IVL           = 000000BH;
SOUTHERNMUSIC = 000000CH;
LAKEBUTLER    = 000000DH;
DOD           = 0000010H;
PERFECTFRET   = 0000014H;
OPCODE        = 0000016H;
SPATIALSOUND  = 0000018H;
KMX           = 0000019H;
AXXES         = 0000020H;


    (* European Group *)
PASSAC         = 20H;
SIEL           = 21H;
SYNTHAXE       = 22H;
HOHNER         = 24H;
TWISTER        = 25H;
SOLTON         = 26H;
JELLINGHAUS    = 27H;
SOUTHWORTH     = 28H;
PPG            = 29H;
JEN            = 2AH;
SSL            = 2BH;
AUDIOVERITRIEB = 2CH;
ELKA           = 2FH;
DYNACORD       = 30H;

    (* Japanese Group *)
KAWAI         = 40H;
ROLAND        = 41H;
KORG          = 42H;
YAMAHA        = 43H;
CASIO         = 44H;
MORIDAIRA     = 45H;
KAMIYA        = 46H;
AKAI          = 47H;
JAPANVICTOR   = 48H;
MEISOSHA      = 49H;
HOSHINOGAKKI  = 4AH;
FUJITSU       = 4BH;
SONY          = 4CH;
NISSHINONPA   = 4DH;
SYSTEMPRODUCT = 4FH;

    (* Universal ID Numbers *)
NC  = 7DH;
NRT = 7EH;
RT  = 7FH;


(* midi.library routine declarations *)
(*
		 FUNCDEF LockMidiBase		-30
		 FUNCDEF UnlockMidiBase		-36
		 FUNCDEF CreateMSource 		-42
		 FUNCDEF DeleteMSource 		-48
		 FUNCDEF FindMSource 		-54
		 FUNCDEF CreateMDest 		-60
		 FUNCDEF DeleteMDest 		-66
		 FUNCDEF FindMDest 		-72
		 FUNCDEF CreateMRoute 		-78
		 FUNCDEF ModifyMRout 		-84
		 FUNCDEF DeleteMRoute 		-90
		 FUNCDEF MRouteSource 		-96
		 FUNCDEF MRouteDest 		-102
		 FUNCDEF MRoutePublic 		-108
		 FUNCDEF GetMidiMsg 		-114
		 FUNCDEF PutMidiMsg 		-120
		 FUNCDEF FreeMidiMsg 		-126
		 FUNCDEF MidiMsgType 		-132
		 FUNCDEF MidiMsgLength 		-138
		 FUNCDEF PutMidiStream 		-144
		 ab V2.0:
		 FUNCDEF LockMRoutes 		-150
		 FUNCDEF UnlockMRoutes 		-156
		 FUNCDEF FlushMDest 		-162
		 FUNCDEF GetMidiPacket 		-168
		 FUNCDEF FreeMidiPacket 	-174
		 FUNCDEF SetDefaultMRouteInfo 	-180
		 FUNCDEF CreateMListSignal 	-186
		 FUNCDEF DeleteMListSignal 	-192
*)

PROCEDURE CreateMDest(name{8} : ADDRESS;
                      image{9}: ImagePtr): MDestPtr;
   CODE -60;


PROCEDURE CreateMListSignal(flags{0}: LONGCARD): MListSignalPtr;
   CODE -186;


PROCEDURE CreateMRoute(source{8}    : MSourcePtr;
                       dest{9}      : MDestPtr;
                       routeinfo{10}: MRouteInfoPtr): MRoutePtr;
   CODE -78;


PROCEDURE CreateMSource(name{8} : ADDRESS;
                        image{9}: ImagePtr): MSourcePtr;
   CODE -42;


PROCEDURE DeleteMDest(dest{8}: MDestPtr);
   CODE -66;


PROCEDURE DeleteMListSignal(signal{8}: MListSignalPtr);
   CODE -192;


PROCEDURE DeleteMRoute(route{8}: MRoutePtr);
   CODE -78;


PROCEDURE DeleteMSource(source{8}: MSourcePtr);
   CODE -48;


PROCEDURE FindMDest(name{8}: ADDRESS): MDestPtr;
   CODE -72;


PROCEDURE FindMSource(name{8}: ADDRESS): MSourcePtr;
   CODE -54;


PROCEDURE FlushMDest(dest{8}:MDestPtr);
   CODE -162;


PROCEDURE FreeMidiMsg(msg{8}: ADDRESS);
   CODE -126;


PROCEDURE FreeMidiPacket(packet{8}: MidiPacketPtr);
   CODE -174;


PROCEDURE GetMidiMsg(dest{8}: MDestPtr): ADDRESS;
   CODE -114;


PROCEDURE GetMidiPacket(dest{8}: MDestPtr): MidiPacketPtr;
   CODE -168;


PROCEDURE LockMidiBase;
   CODE -30;


PROCEDURE LockMRoutes;
   CODE -150;


PROCEDURE MidiMsgLength(msg{8}: ADDRESS): LONGCARD;
   CODE -138;


PROCEDURE MidiMsgType(msg{8}: ADDRESS): LONGCARD;
   CODE -132;


PROCEDURE ModifyMRoute(route{8}       : MRoutePtr;
                       newrouteinfo{9}: MRouteInfoPtr);
   CODE -84;


PROCEDURE MRouteDest(sourcename{8}: ADDRESS;
                     dest{9}      : MDestPtr;
                     routeinfo{10}: MRouteInfoPtr): MRoutePtr;
   CODE -102;


PROCEDURE MRoutePublic(sourcename{8}: ADDRESS;
                       destname{9}  : ADDRESS;
                       routeinfo{10}: MRouteInfoPtr): MRoutePtr;
   CODE -108;


PROCEDURE MRouteSource(source{8}    : MSourcePtr;
                       destname{9}  : ADDRESS;
                       routeinfo{10}: MRouteInfoPtr): MRoutePtr;
   CODE -96;


PROCEDURE PutMidiMsg(source{8}: MSourcePtr;
                     msg   {9}: ADDRESS): BOOLEAN;
   CODE -120;


PROCEDURE PutMidiStream(source{8}    : MSourcePtr;
                        fillbuffer{9}: ADDRESS;
                        buf{10}      : ADDRESS;
                        bufsize{0}   : LONGCARD;
                        cursize{1}   : LONGCARD);
   CODE -144;


PROCEDURE SetDefaultMRouteInfo(dest     {8}: MDestPtr;
                               routeinfo{9}: MRouteInfoPtr);
   CODE -180;


PROCEDURE UnlockMidiBase;
   CODE -36;


PROCEDURE UnlockMRoutes;
   CODE -156;

END Midi.
