[comp.sources.amiga] midi library

ain@j.cc.purdue.edu (Patrick White) (03/25/88)

Program Name:	midi library  (part 1 of 1)
Submitted By:	Pete Yadlowsky <pmy@vivaldi.acc.virginia.edu>
Summary:	This is a midi library
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Untested.

NOTES:
   Not much we could do to test this, so we didn't bother.
   I reshar'ed it to separate docs, etc.
   example code posted to sources as it is source.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	asmsupp.i
#	midi.h
#	midi.i
#	midibase.h
#	midibase.i
# This archive created: Sun Mar 20 16:49:59 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting asmsupp.i '(452 characters)'
cat << \SHAR_EOF > asmsupp.i
*
*   asmsupp.i - some handy (read essential) macros
*

	ifnd	_ASMSUPP_I
_ASMSUPP_I set 1

	ifnd	EXEC_LIBRARIES_I
	include "exec/libraries.i"
	endc

CLEAR	macro
	moveq	#0,\1
	endm

LINKSYS macro
	LINKLIB _LVO\1,\2
	endm

CALLSYS macro
	CALLLIB _LVO\1
	endm

XLIB	macro
	xref	_LVO\1
	endm

FUNCDEF macro
	public	_LVO\1
	LIBDEF	_LVO\1
	endm

push	macro
	movem.l \1,-(sp)
	endm

pop	macro
	movem.l (sp)+,\1
	endm

CLEARA	macro
	suba.l	\1,\1
	endm

	endc

SHAR_EOF
if test 452 -ne "`wc -c asmsupp.i`"
then
echo shar: error transmitting asmsupp.i '(should have been 452 characters)'
fi
echo shar: extracting midi.h '(4193 characters)'
cat << \SHAR_EOF > midi.h
#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
SHAR_EOF
if test 4193 -ne "`wc -c midi.h`"
then
echo shar: error transmitting midi.h '(should have been 4193 characters)'
fi
echo shar: extracting midi.i '(3204 characters)'
cat << \SHAR_EOF > midi.i
; midi/midi.i

	ifnd	MIDI_MIDI_I
MIDI_MIDI_I set 1

	ifnd	EXEC_LISTS_I
	include "exec/lists.i"
	endc

MIDINAME macro
	 dc.b	 'midi.library',0
	 endm

MIDIVERSION equ 1

    STRUCTURE	MSource,LN_SIZE
	APTR	ms_Image
	STRUCT	ms_RPList,MLH_SIZE
	APTR	ms_UserData
	LABEL	sizeof_MSource

; Node Types for MSource nodes
NT_MSOURCE	equ  $20
NT_PERMMSOURCE	equ  $21

    STRUCTURE	MDest,LN_SIZE
	APTR	md_Image
	STRUCT	md_RPList,MLH_SIZE
	APTR	md_DestPort
	APTR	md_UserData
	LABEL	sizeof_MDest

; Node Types for MDest nodes
NT_MDEST	equ  $22
NT_PERMMDEST	equ  $23

    STRUCTURE	RIMatch,0
	UBYTE	rim_count
	STRUCT	rim_match,3
	LABEL	sizeof_RIMatch

    STRUCTURE	MRouteInfo,0
	UWORD	ri_MsgFlags
	UWORD	ri_ChanFlags
	BYTE	ri_ChanOffset
	BYTE	ri_NoteOffset
	STRUCT	ri_SysExMatch,sizeof_RIMatch
	STRUCT	ri_CtrlMatch,sizeof_RIMatch
	LABEL	sizeof_MRouteInfo

; Midi Msg Type Flags for RouteInfo and returned by MidiMsgType

MMF_CHAN       equ  $00ff
MMF_NOTEOFF    equ  $0001
MMF_NOTEON     equ  $0002
MMF_POLYPRESS  equ  $0004
MMF_CTRL       equ  $0008
MMF_PROG       equ  $0010
MMF_CHANPRESS  equ  $0020
MMF_PITCHBEND  equ  $0040
MMF_MODE       equ  $0080

MMF_SYSCOM     equ  $0100
MMF_SYSRT      equ  $0200
MMF_SYSEX      equ  $0400

    STRUCTURE	MRoutePtr,MLN_SIZE
	APTR	rp_Route
	LABEL	sizeof_MRoutePtr

    STRUCTURE	MRoute,0
	APTR	mr_Source
	APTR	mr_Dest
	STRUCT	mr_SRoutePtr,sizeof_MRoutePtr
	STRUCT	mr_DRoutePtr,sizeof_MRoutePtr
	STRUCT	mr_RouteInfo,sizeof_MRouteInfo
	LABEL	sizeof_MRoute


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

; Status Bytes

   ; Channel Voice Messages (1sssnnnn)
MS_NOTEOFF    equ $80
MS_NOTEON     equ $90
MS_POLYPRESS  equ $A0
MS_CTRL       equ $B0
MS_MODE       equ $B0
MS_PROG       equ $C0
MS_CHANPRESS  equ $D0
MS_PITCHBEND  equ $E0

   ; System Common Messages
MS_SYSEX      equ $F0
MS_SONGPOS    equ $F2
MS_SONGSELECT equ $F3
MS_TUNEREQ    equ $F6
MS_EOX	      equ $F7

   ; System Real Time Messages
MS_CLOCK      equ $F8
MS_START      equ $FA
MS_CONTINUE   equ $FB
MS_STOP       equ $FC
MS_ACTVSENSE  equ $FE
MS_RESET      equ $FF


; Standard Controllers (from MMA - 8-86)

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

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

; Channel Modes

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


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

MID_SCI      equ $01
MID_BIGBRIAR equ $02
MID_OCTAVEPLATEAU equ $03
MID_MOOG     equ $04
MID_PASSPORT equ $05
MID_LEXICON  equ $06

MID_OBERHEIM equ $10
MID_PAIA     equ $11
MID_SIMMONS  equ $12
MID_FAIRLIGHT equ $14

MID_BONTEMPI equ $20
MID_SIEL     equ $21
MID_SYNTHAXE equ $23

MID_KAWAI    equ $40
MID_ROLAND   equ $41
MID_KORG     equ $42
MID_YAMAHA   equ $43

; special Sys/Ex ID numbers: Non-Commercial, Non-Real Time, Real Time
MID_NC	equ $7d
MID_NRT equ $7e
MID_RT	equ $7f

	endc
SHAR_EOF
if test 3204 -ne "`wc -c midi.i`"
then
echo shar: error transmitting midi.i '(should have been 3204 characters)'
fi
echo shar: extracting midibase.h '(1206 characters)'
cat << \SHAR_EOF > midibase.h
#ifndef MIDI_MIDIBASE_H
#define MIDI_MIDIBASE_H

/* midi.library MidiBase & related definitions (not for the casual midi user) */

#ifndef EXEC_LIBRARIES_H
 #include <exec/libraries.h>
#endif

#ifndef EXEC_SEMAPHORES_H
 #include <exec/semaphores.h>
#endif
 
#ifndef LIBRARIES_DOS_H
 #include <libraries/dos.h>
#endif

#ifndef MIDI_MIDI_H
 #include <midi/midi.h>
#endif
 

struct MidiBase {
    struct Library libnode;
    struct List SourceList,DestList;
    struct SignalSemaphore ListSemaphore;   /* blocks Source/Dest list management */
    struct SignalSemaphore RouteSemaphore;  /* blocks RPList management & msg routing */
    ULONG SegList;
    APTR  SysBase,DosBase;
};

struct MTaskInfo {
	/* set by caller */
    char *Name;
    WORD Pri;
    void (*Entry)();
    UWORD Stack;

    UWORD Sources;
    struct MNodeInfo *SourceList;
    UWORD Dests;
    struct MNodeInfo *DestList;

	/* set by midi.library */
    struct SignalSemaphore Semaphore;	/* locks task */

    UWORD UsageCount;			/* task's usage count */
    struct MsgPort *TaskPort;		/* task's MsgPort */
    BPTR Segment;			/* task's Segment */
};

struct MNodeInfo {
    char *Name;
    struct Image *Image;
    APTR Node;
};

#endif
SHAR_EOF
if test 1206 -ne "`wc -c midibase.h`"
then
echo shar: error transmitting midibase.h '(should have been 1206 characters)'
fi
echo shar: extracting midibase.i '(1500 characters)'
cat << \SHAR_EOF > midibase.i
; midi/midibase.i

	ifnd	MIDI_MIDIBASE_I
MIDI_MIDIBASE_I set 1

	ifnd	EXEC_LIBRARIES_I
	include "exec/libraries.i"
	endc

	ifnd	EXEC_SEMAPHORES_I
	include "exec/semaphores.i"
	endc

	ifnd	LIBRARIES_DOS_I
	include "libraries/dos.i"
	endc

	ifnd	MIDI_MIDI_I
	include "midi/midi.i"
	endc


    STRUCTURE	MidiBase,LIB_SIZE	; Library Base
	STRUCT	ml_SourceList,LH_SIZE	    ; Source List
	STRUCT	ml_DestList,LH_SIZE	    ; Dest List

	STRUCT	ml_ListSemaphore,SS_SIZE    ; locks source/dest lists - blocks Src & Dst list management
					    ; (locked when LockBase is called)
	STRUCT	ml_RouteSemaphore,SS_SIZE   ; locks routes - blocks msg routing & RPList management in Src & Dst
	ULONG	ml_SegList		    ; Segment List for the library
	ULONG	ml_SysBase		    ; SysBase
	ULONG	ml_DosBase		    ; DosBase

	LABEL	sizeof_MidiBase


    STRUCTURE	MTaskInfo,0 ; Task info structure for PermNodes
	APTR	ti_Name 	; Process Name
	WORD	ti_Pri		; Process Priority
	APTR	ti_Entry	; Entry point
	UWORD	ti_Stack	; Stack Size

	UWORD	ti_Sources	; source count
	APTR	ti_SourceList	; source list
	UWORD	ti_Dests	; dest count
	APTR	ti_DestList	; dest list

	STRUCT	ti_Semaphore,SS_SIZE	; signal semaphore for locking this task

	UWORD	ti_UsageCount
	APTR	ti_TaskPort	; task's MsgPort
	BPTR	ti_Segment	; BPTR pointer to tasks segment
	LABEL	sizeof_MTaskInfo


    STRUCTURE	MNodeInfo,0 ; PermNode info structure
	APTR	ni_Name 	; Node Name
	APTR	ni_Image	; Node Image
	APTR	ni_Node 	; Node pointer
	LABEL	sizeof_MNodeInfo

	endc
SHAR_EOF
if test 1500 -ne "`wc -c midibase.i`"
then
echo shar: error transmitting midibase.i '(should have been 1500 characters)'
fi
#	End of shell archive
exit 0

ain@j.cc.purdue.edu (Patrick White) (03/25/88)

Program Name:	midi library  (lib source)
Submitted By:	Pete Yadlowsky <pmy@vivaldi.acc.virginia.edu>
Summary:	This is a midi library
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Untested.

NOTES:
   Not much we could do to test this, so we didn't bother.
   I reshar'ed it to separate docs, etc.


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	Makefile
#	credst.asm
#	crerte.asm
#	cresrc.asm
#	deldst.asm
#	delrte.asm
#	delsrc.asm
#	finddst.asm
#	findsrc.asm
#	freemsg.asm
#	getmsg.asm
#	lockbase.asm
#	midilvo.asm
#	modrte.asm
#	msglen.asm
#	msgtype.asm
#	putmsg.asm
#	putstr.asm
#	rtedst.asm
#	rtepub.asm
#	rtesrc.asm
#	unlockba.asm
# This archive created: Sun Mar 20 16:45:19 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting Makefile '(381 characters)'
cat << \SHAR_EOF > Makefile
# midi.lib makefile

CFLAGS=-n +b
AFLAGS=

MIDI_LIB=\
 credst.o crerte.o cresrc.o deldst.o delrte.o delsrc.o finddst.o\
 findsrc.o freemsg.o getmsg.o lockbase.o modrte.o msglen.o msgtype.o\
 putmsg.o putstr.o rtedst.o rtepub.o rtesrc.o unlockba.o midilvo.o

all: midi.lib

midi.lib: $(MIDI_LIB)
	lb $@ $(MIDI_LIB)

#midilvo.asm: /lib/midibase.asm
#	 makelvo /lib/midibase midilvo

SHAR_EOF
if test 381 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 381 characters)'
fi
echo shar: extracting credst.asm '(217 characters)'
cat << \SHAR_EOF > credst.asm
	public	_MidiBase,_LVOCreateMDest

; struct MDest *CreateMDest (name,image)
; char *name;
; struct Image *image;

	public	_CreateMDest
_CreateMDest
	movem.l  4(sp),a0-a1
	move.l	_MidiBase,a6
	jmp	_LVOCreateMDest(a6)

SHAR_EOF
if test 217 -ne "`wc -c credst.asm`"
then
echo shar: error transmitting credst.asm '(should have been 217 characters)'
fi
echo shar: extracting crerte.asm '(316 characters)'
cat << \SHAR_EOF > crerte.asm
	public	_MidiBase,_LVOCreateMRoute

; struct Route *CreateMRoute (source,dest,routeinfo)
; Struct MSource *source;
; Struct MDest *dest;
; Struct MRouteInfo *routeinfo;

	public	_CreateMRoute
_CreateMRoute
	movem.l a2,-(sp)
	movem.l 8(sp),a0-a2
	move.l	_MidiBase,a6
	jsr	_LVOCreateMRoute(a6)
	movem.l (sp)+,a2
	rts

SHAR_EOF
if test 316 -ne "`wc -c crerte.asm`"
then
echo shar: error transmitting crerte.asm '(should have been 316 characters)'
fi
echo shar: extracting cresrc.asm '(229 characters)'
cat << \SHAR_EOF > cresrc.asm
	public	_MidiBase,_LVOCreateMSource

; struct MSource *CreateMSource (name,image)
; char *name;
; struct Image *image;

	public	_CreateMSource
_CreateMSource
	movem.l  4(sp),a0-a1
	move.l	_MidiBase,a6
	jmp	_LVOCreateMSource(a6)

SHAR_EOF
if test 229 -ne "`wc -c cresrc.asm`"
then
echo shar: error transmitting cresrc.asm '(should have been 229 characters)'
fi
echo shar: extracting deldst.asm '(177 characters)'
cat << \SHAR_EOF > deldst.asm
	public	_MidiBase,_LVODeleteMDest

; DeleteMDest (dest)
; struct MDest *dest;

	public	_DeleteMDest
_DeleteMDest
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVODeleteMDest(a6)

SHAR_EOF
if test 177 -ne "`wc -c deldst.asm`"
then
echo shar: error transmitting deldst.asm '(should have been 177 characters)'
fi
echo shar: extracting delrte.asm '(185 characters)'
cat << \SHAR_EOF > delrte.asm
	public	_MidiBase,_LVODeleteMRoute

; DeleteMRoute (route)
; struct MRoute *route;

	public	_DeleteMRoute
_DeleteMRoute
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVODeleteMRoute(a6)

SHAR_EOF
if test 185 -ne "`wc -c delrte.asm`"
then
echo shar: error transmitting delrte.asm '(should have been 185 characters)'
fi
echo shar: extracting delsrc.asm '(193 characters)'
cat << \SHAR_EOF > delsrc.asm
	public	_MidiBase,_LVODeleteMSource

; DeleteMSource (source)
; struct MSource *source;

	public	_DeleteMSource
_DeleteMSource
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVODeleteMSource(a6)

SHAR_EOF
if test 193 -ne "`wc -c delsrc.asm`"
then
echo shar: error transmitting delsrc.asm '(should have been 193 characters)'
fi
echo shar: extracting finddst.asm '(173 characters)'
cat << \SHAR_EOF > finddst.asm
	public	_MidiBase,_LVOFindMDest

; struct MDest *FindMDest (name)
; char *name;

	public	_FindMDest
_FindMDest
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOFindMDest(a6)

SHAR_EOF
if test 173 -ne "`wc -c finddst.asm`"
then
echo shar: error transmitting finddst.asm '(should have been 173 characters)'
fi
echo shar: extracting findsrc.asm '(185 characters)'
cat << \SHAR_EOF > findsrc.asm
	public	_MidiBase,_LVOFindMSource

; struct MSource *FindMSource (name)
; char *name;

	public	_FindMSource
_FindMSource
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOFindMSource(a6)

SHAR_EOF
if test 185 -ne "`wc -c findsrc.asm`"
then
echo shar: error transmitting findsrc.asm '(should have been 185 characters)'
fi
echo shar: extracting freemsg.asm '(169 characters)'
cat << \SHAR_EOF > freemsg.asm
	public	_MidiBase,_LVOFreeMidiMsg

; FreeMidiMsg (msg)
; UBYTE *msg;

	public	_FreeMidiMsg
_FreeMidiMsg
	movem.l 4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOFreeMidiMsg(a6)

SHAR_EOF
if test 169 -ne "`wc -c freemsg.asm`"
then
echo shar: error transmitting freemsg.asm '(should have been 169 characters)'
fi
echo shar: extracting getmsg.asm '(179 characters)'
cat << \SHAR_EOF > getmsg.asm
	public	_MidiBase,_LVOGetMidiMsg

; UBYTE *GetMidiMsg (dest)
; struct MDest *dest

	public	_GetMidiMsg
_GetMidiMsg
	movem.l 4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOGetMidiMsg(a6)

SHAR_EOF
if test 179 -ne "`wc -c getmsg.asm`"
then
echo shar: error transmitting getmsg.asm '(should have been 179 characters)'
fi
echo shar: extracting lockbase.asm '(138 characters)'
cat << \SHAR_EOF > lockbase.asm
	public	_MidiBase,_LVOLockMidiBase

; LockMidiBase()

	public	_LockMidiBase
_LockMidiBase
	move.l	_MidiBase,a6
	jmp	_LVOLockMidiBase(a6)

SHAR_EOF
if test 138 -ne "`wc -c lockbase.asm`"
then
echo shar: error transmitting lockbase.asm '(should have been 138 characters)'
fi
echo shar: extracting midilvo.asm '(606 characters)'
cat << \SHAR_EOF > midilvo.asm
; midilvo.asm - library routine definitions
; file created automatically by MakeLVO

	include "exec/types.i"
	include "exec/libraries.i"
	include "asmsupp.i"

	LIBINIT
	FUNCDEF LockMidiBase
	FUNCDEF UnlockMidiBase
	FUNCDEF CreateMSource
	FUNCDEF DeleteMSource
	FUNCDEF FindMSource
	FUNCDEF CreateMDest
	FUNCDEF DeleteMDest
	FUNCDEF FindMDest
	FUNCDEF CreateMRoute
	FUNCDEF ModifyMRoute
	FUNCDEF DeleteMRoute
	FUNCDEF MRouteSource
	FUNCDEF MRouteDest
	FUNCDEF MRoutePublic
	FUNCDEF GetMidiMsg
	FUNCDEF PutMidiMsg
	FUNCDEF FreeMidiMsg
	FUNCDEF MidiMsgType
	FUNCDEF MidiMsgLength
	FUNCDEF PutMidiStream

	end
SHAR_EOF
if test 606 -ne "`wc -c midilvo.asm`"
then
echo shar: error transmitting midilvo.asm '(should have been 606 characters)'
fi
echo shar: extracting modrte.asm '(237 characters)'
cat << \SHAR_EOF > modrte.asm
	public	_MidiBase,_LVOModifyMRoute

; ModifyMRoute (route,newrouteinfo)
; struct MRoute *route;
; struct MRouteInfo *newrouteinfo;

	public	_ModifyMRoute
_ModifyMRoute
	movem.l 4(sp),a0-a1
	move.l	_MidiBase,a6
	jmp	_LVOModifyMRoute(a6)

SHAR_EOF
if test 237 -ne "`wc -c modrte.asm`"
then
echo shar: error transmitting modrte.asm '(should have been 237 characters)'
fi
echo shar: extracting msglen.asm '(178 characters)'
cat << \SHAR_EOF > msglen.asm
	public	_MidiBase,_LVOMidiMsgLength

; MidiMsgLength (msg)
; UBYTE *msg;

	public	_MidiMsgLength
_MidiMsgLength
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOMidiMsgLength(a6)

SHAR_EOF
if test 178 -ne "`wc -c msglen.asm`"
then
echo shar: error transmitting msglen.asm '(should have been 178 characters)'
fi
echo shar: extracting msgtype.asm '(168 characters)'
cat << \SHAR_EOF > msgtype.asm
	public	_MidiBase,_LVOMidiMsgType

; MidiMsgType (msg)
; UBYTE *msg;

	public	_MidiMsgType
_MidiMsgType
	move.l	4(sp),a0
	move.l	_MidiBase,a6
	jmp	_LVOMidiMsgType(a6)

SHAR_EOF
if test 168 -ne "`wc -c msgtype.asm`"
then
echo shar: error transmitting msgtype.asm '(should have been 168 characters)'
fi
echo shar: extracting putmsg.asm '(200 characters)'
cat << \SHAR_EOF > putmsg.asm
	public	_MidiBase,_LVOPutMidiMsg

; PutMidiMsg (source,msg)
; struct MSource *source;
; UBYTE *msg;

	public	_PutMidiMsg
_PutMidiMsg
	movem.l 4(sp),a0-a1
	move.l	_MidiBase,a6
	jmp	_LVOPutMidiMsg(a6)

SHAR_EOF
if test 200 -ne "`wc -c putmsg.asm`"
then
echo shar: error transmitting putmsg.asm '(should have been 200 characters)'
fi
echo shar: extracting putstr.asm '(360 characters)'
cat << \SHAR_EOF > putstr.asm
	public	_MidiBase,_LVOPutMidiStream

; void PutMidiStream (source,fillbuffer,buf,bufsize,cursize)
; struct MSource *source;
; ULONG (*fillbuffer)();
; UBYTE *buf;
; ULONG bufsize,cursize;

	public	_PutMidiStream
_PutMidiStream
	movem.l a2,-(sp)
	movem.l 8(sp),a0-a2
	movem.l 20(sp),d0-d1
	move.l	_MidiBase,a6
	jsr	_LVOPutMidiStream(a6)
	movem.l (sp)+,a2
	rts

SHAR_EOF
if test 360 -ne "`wc -c putstr.asm`"
then
echo shar: error transmitting putstr.asm '(should have been 360 characters)'
fi
echo shar: extracting rtedst.asm '(301 characters)'
cat << \SHAR_EOF > rtedst.asm
	public	_MidiBase,_LVOMRouteDest

; struct MRoute *MRouteDest (sourcename,dest,midiinfo)
; char *sourcename;
; struct MDest *dest;
; struct MidiInfo *midiinfo;

	public	_MRouteDest
_MRouteDest
	movem.l a2,-(sp)
	movem.l 8(sp),a0-a2
	move.l	_MidiBase,a6
	jsr	_LVOMRouteDest(a6)
	movem.l (sp)+,a2
	rts

SHAR_EOF
if test 301 -ne "`wc -c rtedst.asm`"
then
echo shar: error transmitting rtedst.asm '(should have been 301 characters)'
fi
echo shar: extracting rtepub.asm '(307 characters)'
cat << \SHAR_EOF > rtepub.asm
	public	_MidiBase,_LVOMRoutePublic

; struct MRoute *MRoutePublic (sourcename,destname,routeinfo)
; char *sourcename,*destname;
; struct MRouteInfo *routeinfo;

	public	_MRoutePublic
_MRoutePublic
	movem.l a2,-(sp)
	movem.l 8(sp),a0-a2
	move.l	_MidiBase,a6
	jsr	_LVOMRoutePublic(a6)
	movem.l (sp)+,a2
	rts

SHAR_EOF
if test 307 -ne "`wc -c rtepub.asm`"
then
echo shar: error transmitting rtepub.asm '(should have been 307 characters)'
fi
echo shar: extracting rtesrc.asm '(317 characters)'
cat << \SHAR_EOF > rtesrc.asm
	public	_MidiBase,_LVOMRouteSource

; struct MRoute *MRouteSource (source,destname,routeinfo)
; Struct MSource *source;
; char *destname;
; Struct MRouteInfo *routeinfo;

	public	_MRouteSource
_MRouteSource
	movem.l a2,-(sp)
	movem.l 8(sp),a0-a2
	move.l	_MidiBase,a6
	jsr	_LVOMRouteSource(a6)
	movem.l (sp)+,a2
	rts

SHAR_EOF
if test 317 -ne "`wc -c rtesrc.asm`"
then
echo shar: error transmitting rtesrc.asm '(should have been 317 characters)'
fi
echo shar: extracting unlockba.asm '(148 characters)'
cat << \SHAR_EOF > unlockba.asm
	public	_MidiBase,_LVOUnlockMidiBase

; UnlockMidiBase()

	public	_UnlockMidiBase
_UnlockMidiBase
	move.l	_MidiBase,a6
	jmp	_LVOUnlockMidiBase(a6)

SHAR_EOF
if test 148 -ne "`wc -c unlockba.asm`"
then
echo shar: error transmitting unlockba.asm '(should have been 148 characters)'
fi
#	End of shell archive
exit 0

ain@j.cc.purdue.edu (Patrick White) (03/25/88)

Program Name:	midi library  (example code)
Submitted By:	Pete Yadlowsky <pmy@vivaldi.acc.virginia.edu>
Summary:	This is a midi library
Poster Boy:  Pat White  (ain@j.cc.purdue.edu)
Untested.

NOTES:
   Not much we could do to test this, so we didn't bother.
   I reshar'ed it to separate docs, etc.
   example source


-- Pat White   (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain  BITNET: PATWHITE@PURCCVM   PHONE: (317) 743-8421
U.S.  Mail:  320 Brown St. apt. 406,    West Lafayette, IN 47906

========================================

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	hr.c
#	ht.c
#	makefile
#	r.c
#	rsx.c
#	tsx.c
# This archive created: Sun Mar 20 16:42:58 1988
# By:	Patrick White (PUCC Land, USA)
echo shar: extracting hr.c '(2589 characters)'
cat << \SHAR_EOF > hr.c
/* hex receive from midi.library */
/*
    display incoming MIDI messages in Hex to the console.

    Shows proper method of waiting for, receiving, processing, and disposing
    of MIDI messages.
*/


#include <libraries/dos.h>
#include <clib/macros.h>
#include <midi/midi.h>
#include <functions.h>

#include <stdio.h>

void *MidiBase;

struct MDest *dest;
struct MRoute *route;
UBYTE *msg;		    /* buffer this in case we get shut down before freeing the current message */

main(argc,argv)
char **argv;
{
    char *sname = "MidiIn";
    static struct MRouteInfo routeinfo = { -1, -1 };	/* route spec's: receive all */

    printf ("MIDI Hex Display\n");

    if (argc > 1 && *argv[1] == '?') {
	printf ("usage: hr [source]\n");
	exit (1);
    }

    if (!(MidiBase = OpenLibrary (MIDINAME,MIDIVERSION))) {
	printf ("can't open midi.library\n");
	goto clean;
    }

    if (argc > 1) {	    /* if there's an argument, use it as an alt. source name */
	sname = argv[1];
    }
			    /* create out dest node (private) */
    if (!(dest = CreateMDest (NULL,NULL))) {
	printf ("can't create Dest\n");
	goto clean;
    }
			    /* create out route to MidiIn or whatever the user specified */
    if (!(route = MRouteDest (sname, dest, &routeinfo))) {
	printf ("can't create Route (can't find source \"%s\"?)\n",sname);
	goto clean;
    }

    process(dest);	    /* process until shutdown */

clean:
    cleanup();
}

_abort()		    /* abort routine called when CTRL-C is hit (Aztec) */
{
    fflush(stdout);
    cleanup();
    exit (1);
}

cleanup()
{
    if (msg) FreeMidiMsg (msg);
    if (route) DeleteMRoute (route);
    if (dest) DeleteMDest (dest);
    if (MidiBase) CloseLibrary (MidiBase);
}

process (dest)
struct MDest *dest;
{
    ULONG flags = SIGBREAKF_CTRL_C | (1L << dest->DestPort->mp_SigBit);

    while (!(Wait(flags) & SIGBREAKF_CTRL_C)) { 	/* wait until we get a message or CTRL-C is hit, quit on CTRL-C */
	while (msg = GetMidiMsg (dest)) {		/* get a message */
	    dumpmsg (msg);				/* print it */
	    FreeMidiMsg (msg);				/* free it */
	}
    }
}


dumpmsg (msg)
UBYTE *msg;
{
    long len = MidiMsgLength (msg);		/* find out how long the message is */

    if (*msg == MS_SYSEX) {			/* if it's a System Exclusive message... */
	dump (msg,MIN(len,8));			    /* only print the first 8 bytes */
	printf ("... (%ld bytes)\n",len);
    }
    else {					/* otherwise */
	dump (msg,MidiMsgLength(msg));		    /* print the whole message */
	printf ("\n");
    }
}


dump (s,len)					/* print len bytes in hex */
UBYTE *s;
long len;
{
    while (len--) printf ("%02x ",*s++);
}
SHAR_EOF
if test 2589 -ne "`wc -c hr.c`"
then
echo shar: error transmitting hr.c '(should have been 2589 characters)'
fi
echo shar: extracting ht.c '(1784 characters)'
cat << \SHAR_EOF > ht.c
/* simplified Hex Transmit to midi */
/*
    Shows usage of PutMidiStream() when buffer size is known and of managable
    size.
*/


#include <midi/midi.h>
#include <functions.h>

void *MidiBase;

main (argc,argv)
char **argv;
{
    struct MSource *source=0;
    struct MRoute *route=0;
    static struct MRouteInfo routeinfo = { -1, -1 };	/* route spec's: transmit all */
    char buf[128];		/* buffer used for midi transfer */
    long len;
    extern int Enable_Abort;

    Enable_Abort = 0;		/* disable auto CTRL-C termination */

    if (argc < 2) {
	printf ("MIDI Hex Transmit\n");
	printf ("usage: ht <hex byte>...\n");
	exit (1);
    }

    if (!(MidiBase = OpenLibrary (MIDINAME,MIDIVERSION))) {
	printf ("can't open midi.library\n");
	goto clean;
    }
				/* create our Source node (private) */
    if (!(source = CreateMSource (NULL,NULL))) {
	printf ("can't create Source\n");
	goto clean;
    }
				/* create out Route to MidiOut */
    if (!(route = MRouteSource (source,"MidiOut",&routeinfo))) {
	printf ("can't create Route (can't find MidiOut?)\n");
	goto clean;
    }
				/* parse the command line for hex bytes, make into an array */
    len = makestream (buf,argc-1,argv+1);
				/* convert array to midi messages and send */
    PutMidiStream (source,NULL,buf,len,len);

clean:				/* clean up */
    if (route) DeleteMRoute (route);
    if (source) DeleteMSource (source);
    if (MidiBase) CloseLibrary (MidiBase);
}

makestream (buf,argc,argv)	/* convert args into an array of bytes, return length */
char *buf;
char **argv;
{
    int len=0;

    while (argc--) {
	*buf++ = atox(*argv++);
	len++;
    }
    return len;
}


atox(cp)			/* like atoi() but read string as hex rather than decimal */
char *cp;
{
    int x;

    sscanf (cp,"%x",&x);
    return x;
}
SHAR_EOF
if test 1784 -ne "`wc -c ht.c`"
then
echo shar: error transmitting ht.c '(should have been 1784 characters)'
fi
echo shar: extracting makefile '(190 characters)'
cat << \SHAR_EOF > makefile
all: ht hr rsx tsx r

ht: ht.o
	ln +q ht.o -lmidi -lc

hr: hr.o
	ln +q hr.o -lmidi -lc

rsx: rsx.o
	ln +q rsx.o -lmidi -lc

tsx: tsx.o
	ln +q tsx.o -lmidi -lc

r: r.o
	ln +q r.o -lmidi -lc

SHAR_EOF
if test 190 -ne "`wc -c makefile`"
then
echo shar: error transmitting makefile '(should have been 190 characters)'
fi
echo shar: extracting r.c '(7600 characters)'
cat << \SHAR_EOF > r.c
/* simple MIDI router */
/*
    This is considered an example even though it's included with the utility
    set.  It shows methods for scanning public node lists and managing routes
    to public nodes.  This might be used as the skeleton for a graphics-based
    route manager.
*/

#include <exec/types.h>
#include <exec/lists.h>
#include <midi/midibase.h>
#include <functions.h>

#define DeclareMinList(list)\
    struct MinList list = { (void *)&list.mlh_Tail, NULL, (void *)&list.mlh_Head }


struct MidiBase *MidiBase;

DeclareMinList(routelist);	    /* list or MRoutePtr's for maintaining routes that we create */

main()
{
    char b[128];
    extern int Enable_Abort;

    Enable_Abort = 0;		    /* disable CTRL-C */

    if (!(MidiBase = (void *)OpenLibrary (MIDINAME,MIDIVERSION))) {
	printf ("can't open midi.library\n");
	goto clean;
    }

    printf ("MIDI Router (type ? for help)\n");
				    /* process commands */
    for (;;) {
	printf ("route> ");
	if (gets(b) && !parse(b)) break;
    }

clean:
    if (MidiBase) CloseLibrary (MidiBase);
}

parse(s)
char *s;
{
    switch (tolower(*s++)) {
	case 'x':           /* quit */
	case 'q':
		zaproutelist();
		return 0;

	case 'l':           /* list */
		list();
		break;

	case 'a':           /* add */
		addroute(s);
		break;

	case 'm':           /* modify */
		modroute(s);
		break;

	case 'r':           /* remove */
		remroute(s);
		break;

	case 'h':           /* help */
	case '?':
		help();
		break;
    }
    return 1;
}


help()
{
    printf ("\n");
    printf ("Simple MIDI Router\n");
    printf ("   ? - help\n");
    printf ("   a <src> <dst> <MsgFlags> <ChanFlags> <ChanOffset> <NoteOffset> - add a route\n");
    printf ("   m <num> <MsgFlags> <ChanFlags> <ChanOffset> <NoteOffset> - modify a route\n");
    printf ("   r <num> - rem a route\n");
    printf ("   l - list\n");
    printf ("   q - quit\n");
    printf ("\n");
}


list()
{
			    /* list public sources */
    printf ("\nSources:\n");
    listnames (&MidiBase->SourceList);
			    /* list public dests */
    printf ("\nDests:\n");
    listnames (&MidiBase->DestList);
			    /* list our routes */
    printf ("\nRoutes:\n");
    listroutes();
    printf ("\n");
}


/*
    Lists names in a specified list (like MidiBase->SourceList or MidiBase->DestList).
    This requires locking the lists to prevent changes while scanning them.
    Ideally, if a similar routine is going to take any large amount of time
    or can be halted by the user in mid-stream, it should take a snapshot
    of all the data it wishes to handle rather than locking the lists for
    the whole process.	Locking the lists prevents anyone else from Creating
    or Deleting a node or Finding a node.
*/

listnames(list)
struct List *list;
{
    struct Node *node;

    LockMidiBase();
    for (node = list->lh_Head; node->ln_Succ; node=node->ln_Succ) {
	printf (" %s\n",node->ln_Name);
    }
    UnlockMidiBase();
}


/* Displays our route list. */

listroutes()
{
    struct MinNode *node;
    int i;

    for (i=0,node = routelist.mlh_Head; node->mln_Succ; i++,node=node->mln_Succ) {
	prtroute (i,node);
    }
}


/*
    Displays info about one of our routes.  In order to display the node
    names, we need to lock the lists to ensure validity of the nodes.  This
    one is done correctly:  it locks the lists, copies the names of the nodes
    if present, unlocks the lists, and THEN prints.
*/

prtroute (i,rp)
struct MRoutePtr *rp;
{
    struct MRoute *route = rp->Route;
    struct MRouteInfo *ri = &route->RouteInfo;
    struct MSource *source;
    struct MDest *dest;
    char sname[64], dname[64];

    LockMidiBase();			/* lock node lists */

    if (source = route->Source) {	/* if the source still exists */
	if (source->Node.ln_Name)	    /* and it has a name (public, for this program this should always be true) */
	    sprintf (sname,"\"%s\"",source->Node.ln_Name);      /* copy the name */
	else
	    strcpy (sname,"(private)");
    }
    else {
	strcpy (sname,"(removed)");
    }

    if (dest = route->Dest) {		/* do the same for the dest */
	if (dest->Node.ln_Name)
	    sprintf (dname,"\"%s\"",dest->Node.ln_Name);
	else
	    strcpy (dname,"(private)");
    }
    else {
	strcpy (dname,"(removed)");
    }

    UnlockMidiBase();			/* unlock the lists */

					/* print */
    printf (" %2d: %08lxH %s->%s %04x %04x %d %d\n", i, route, sname, dname, ri->MsgFlags, ri->ChanFlags, ri->ChanOffset, ri->NoteOffset);
}


/* delete all routes in our route list, used on exit */

zaproutelist()
{
    struct MRoutePtr *rp;

    while (rp = (struct MRoutePtr *)RemHead(&routelist)) {
	DeleteMRoute(rp->Route);
	free (rp);
    }
}


/* adds a new route based on the command line in s */

addroute(s)
char *s;
{
    char sname[64],dname[64];
    struct MRouteInfo ri;
    struct MRoutePtr *rp=NULL;
    struct MRoute *route=NULL;
    int chanoffset,noteoffset;
    void *calloc();

    setmem (&ri,sizeof ri,0);
    if (sscanf (s,"%s%s%x%x%d%d",sname,dname,&ri.MsgFlags,&ri.ChanFlags,&chanoffset,&noteoffset) != 6) {
	printf ("syntax error\n");
	goto clean;
    }
    ri.ChanOffset = chanoffset;
    ri.NoteOffset = noteoffset;

				/* allocate a RoutePtr to hold ptr to our route */
    if (!(rp = calloc(1,sizeof *rp))) {
	printf ("out of memory\n");
	goto clean;
    }
				/* try to create the route */
    if (!(route = MRoutePublic(sname,dname,&ri))) {
	printf ("error creating route\n");
	goto clean;
    }

    rp->Route = route;		/* set route pointer in our list */
    AddTail (&routelist,rp);	/* add to our list */
    printf ("  Route %d added.\n",findpos (&routelist,rp));
    return 0;

clean:
    if (route) DeleteMRoute (route);
    if (rp) free (rp);
    return -1;
}


/* modifies a existing route based on the command line in s */

modroute(s)
char *s;
{
    int num;
    struct MRouteInfo ri;
    struct MRoutePtr *rp;
    struct Node *findnode();
    int chanoffset,noteoffset;

    setmem (&ri,sizeof ri,0);
    if (sscanf (s,"%d%x%x%d%d",&num,&ri.MsgFlags,&ri.ChanFlags,&chanoffset,&noteoffset) != 5) {
	printf ("syntax error\n");
	goto clean;
    }
    ri.ChanOffset = chanoffset;
    ri.NoteOffset = noteoffset;

				/* find our routeptr by position */
    if (!(rp = (struct MRoutePtr *)findnode(&routelist,num))) {
	printf ("can't find route\n");
	goto clean;
    }
				/* modify the route */
    ModifyMRoute (rp->Route,&ri);
    printf ("  Route %d modified.\n",num);
    return 0;

clean:
    return -1;
}


/* removes the route specifed in the command line s */

remroute(s)
char *s;
{
    int num;
    struct MRoutePtr *rp;
    struct Node *findnode();

    if (sscanf (s,"%d",&num) != 1) {
	printf ("syntax error\n");
	goto clean;
    }
			/* find our route ptr by number */
    if (!(rp = (struct MRoutePtr *)findnode(&routelist,num))) {
	printf ("can't find route\n");
	goto clean;
    }
			/* remove from our list */
    Remove (rp);
    DeleteMRoute (rp->Route);	/* delete the route */
    free (rp);			/* free our route ptr */
    printf ("  Route %d removed.\n",num);
    return 0;

clean:
    return -1;
}


/* finds a node by number */

struct Node *findnode (list,num)
struct List *list;
{
    struct Node *node;

    for (node = list->lh_Head; node->ln_Succ; node=node->ln_Succ) {
	if (!num--) return node;
    }
    return 0;
}


/* returns the ordinal position of a node within a list */

findpos (list,match)
struct List *list;
struct Node *match;
{
    struct Node *node;
    int num;

    for (num=0,node = list->lh_Head; node->ln_Succ; num++,node=node->ln_Succ) {
	if (node==match) return num;
    }
    return -1;
}
SHAR_EOF
if test 7600 -ne "`wc -c r.c`"
then
echo shar: error transmitting r.c '(should have been 7600 characters)'
fi
echo shar: extracting rsx.c '(2377 characters)'
cat << \SHAR_EOF > rsx.c
/* simplified receive system exclusive */
/*    receives next sys/ex message and save it to a named file */

/*
    shows usage of GetMidiMsg(), MidiMsgLength(), FreeMidiMsg() and msg
    filtering with routes.
*/

#include <libraries/dos.h>
#include <midi/midi.h>
#include <functions.h>
#include <fcntl.h>

void *MidiBase;

main(argc,argv)
char **argv;
{
    extern int Enable_Abort;
    int fo;				/* output file descriptor */
    UBYTE *msg=0, *getmsg();
    struct MDest *dest=0;
    struct MRoute *route=0;
    static struct MRouteInfo routeinfo = { MMF_SYSEX };     /* receive only sys/ex msg's */
    char *fname;

    printf ("Receive Sys/Ex\n");
    Enable_Abort = 0;			/* disable auto CTRL-C handling */

    if (argc < 2) {
	printf ("usage: rsx <file>\n");
	exit (1);
    }

    fname = argv[1];			/* get file name */

    if (!(MidiBase = OpenLibrary (MIDINAME,MIDIVERSION))) {
	printf ("can't open midi.library\n");
	goto clean;
    }
					/* create our dest node (private) */
    if (!(dest = CreateMDest (NULL,NULL))) {
	printf ("can't create Dest\n");
	goto clean;
    }
					/* create our route to MidiIn */
    if (!(route = MRouteDest ("MidiIn", dest, &routeinfo))) {
	printf ("can't create Route (can't find MidiIn?)\n");
	goto clean;
    }
					/* create our output file */
    if ( (fo=creat(fname,0666)) == -1) {
	printf ("can't open %s\n",fname);
	goto clean;
    }
					/* wait for the next message, save it or skip if terminated */
    if (msg = getmsg(dest)) {
	long len = MidiMsgLength(msg);		/* get message length */

	if (write (fo,msg,(int)len) != len ||	/* won't work for msg's bigger than 64K */
	    close(fo) == -1) {
		printf ("error writing file.\n");
	}
	printf ("sys/ex file \"%s\" saved. (%ld bytes)\n",fname,len);
    }
    else {
	printf ("save aborted.\n");
	close(fo);
	unlink(fname);
    }

clean:
    if (msg) FreeMidiMsg (msg);
    if (route) DeleteMRoute (route);
    if (dest) DeleteMDest (dest);
    if (MidiBase) CloseLibrary (MidiBase);
}


/*
   waits for next msg (will be sys/ex because that's all that our route lets
   through).  Returns pointer to message.  If CTRL-C is hit before a message
   arrives, returns NULL
*/

UBYTE *getmsg (dest)
struct MDest *dest;
{
    ULONG flags = SIGBREAKF_CTRL_C | (1L << dest->DestPort->mp_SigBit);

    if (Wait(flags) & SIGBREAKF_CTRL_C) return 0;
    return GetMidiMsg (dest);
}
SHAR_EOF
if test 2377 -ne "`wc -c rsx.c`"
then
echo shar: error transmitting rsx.c '(should have been 2377 characters)'
fi
echo shar: extracting tsx.c '(1879 characters)'
cat << \SHAR_EOF > tsx.c
/* simplified transmit sys/ex file */
/*    actually transmits entire contents of file, not just sys/ex */

/*
    describes usage of PutMidiStream() limited buffer size and unknown
    stream length.
*/

#include <midi/midi.h>
#include <functions.h>
#include <fcntl.h>

void *MidiBase;

static int fi;			    /* input file descriptor */
UBYTE buf[512]; 		    /* buffer used for transfer */

main(argc,argv)
char **argv;
{
    struct MSource *source=0;
    struct MRoute *route=0;
    static struct MRouteInfo routeinfo = { -1, -1 };	/* support all msg's */
    extern short Enable_Abort;
    char *fname;
    long fillbuffer();

    printf ("Transmit Sys/Ex\n");
    Enable_Abort = 0;			/* disable auto CTRL-C handling */

    if (argc < 2) {
	printf ("usage: tsx <file>\n");
	exit (1);
    }

    fname = argv[1];			/* get file name */

    if (!(MidiBase = OpenLibrary (MIDINAME,MIDIVERSION))) {
	printf ("can't open midi.library\n");
	goto clean;
    }
					/* create our source node (private) */
    if (!(source = CreateMSource (NULL,NULL))) {
	printf ("can't create Source\n");
	goto clean;
    }
					/* create our route to MidiOut */
    if (!(route = MRouteSource (source,"MidiOut",&routeinfo))) {
	printf ("can't create Route (can't find MidiOut?)\n");
	goto clean;
    }
					/* open input file */
    if ( (fi=open(fname,O_RDONLY)) == -1) {
	printf ("can't open %s\n",fname);
	goto clean;
    }
					/* convert file to midi messages */
    PutMidiStream (source,fillbuffer,buf,(long)sizeof buf,0L);

clean:
    if (route) DeleteMRoute (route);
    if (source) DeleteMSource (source);
    if (MidiBase) CloseLibrary (MidiBase);
}



/* fill our buffer with data from the file, called by PutMidiStream() */

static
long fillbuffer()
{
    register long len;

    geta4();			    /* Aztec small data model */
    return (len = read(fi,buf,sizeof buf)) == -1 ? 0 : len;
}
SHAR_EOF
if test 1879 -ne "`wc -c tsx.c`"
then
echo shar: error transmitting tsx.c '(should have been 1879 characters)'
fi
#	End of shell archive
exit 0