/*			 MIDI-System-Exclusive Dumper
		Written, arranged, produced by Carl Ch. v. Loesch.

		V1.0alpha	Saturday 19. 8. 89
Changes:	V1.0beta	Saturday  9. 6. 90
		V1.0gamma	Tuesday  25. 7. 90  now uses midi.library!
		V1.0		Wednesday 15.8. 90  now uses arp.lib too
*/
#include "Lynx.h"
#define	XBUFSIZE	50000L

#include <libraries/ARPbase.h>
EXPORT	struct	ArpBase		*ArpBase;
EXPORT	struct	IntuitionBase	*IntuitionBase;
EXPORT	char	file[FCHARS+DSIZE+1]="", dir[DSIZE+1]="SysX",
		loadname[FCHARS+1]="out.x", savename[FCHARS+1]="in.x";
EXPORT	struct	FileRequester	*freq;
EXPORT	struct	Window		*win;

#include <MIDI/MIDI.h>
EXPORT	struct	MidiBase	*MidiBase;
EXPORT	struct	MSource		*source=0;
EXPORT	struct	MDest		*dest=0;
EXPORT	struct	MRoute		*droute=0, *sroute=0;
EXPORT	struct	MidiPacket	*packet=0;
static	struct	MRouteInfo routeinfo = { MMF_SYSEX };
     /* receive only sys/ex msg's */

struct NewWindow nw = {
	10, 24, 620, 117,
	3, 2, CLOSEWINDOW+RAWKEY, WINDOWCLOSE+WINDOWDEPTH+WINDOWDRAG
	+SMART_REFRESH+WINDOWSIZING+NOCAREREFRESH,
	NULL, NULL, "*| MIDI SysX Dumper V1.0 by Carlo von Loesch '89/90 |*",
	NULL, NULL,
	300, 11, 640, 500,
	WBENCHSCREEN
};

EXPORT	char	name[]="MIDIdump";
EXPORT	char	nomem[] = "Out of RAM";
EXPORT	UBYTE	*xbuffer, ret[77];
EXPORT	FLAG	timer = NO, cons = NO, logon = YES, spool = NO;
EXPORT	long	xlen = 0, sigs, videosig, midisig;
struct	IOStdReq conreq;

_main	() {
	ifnot (ArpBase = OpenLibrary("arp.library",ArpVersion))
		Ciao("No ARP.Library");
	IntuitionBase =	ArpBase -> IntuiBase;
	ifnot (MidiBase = ArpOpenLibrary (MIDINAME,MIDIVERSION))
		Ciao ("No MIDI.Library");

	conreq.io_Data = win = MyOpenWindow (&nw);
	OpenDevice("console.device", NULL, &conreq, NULL); cons=YES;
	ifnot (xbuffer = ArpAlloc (XBUFSIZE)) Ciao (nomem);

	ifnot (freq = ArpAllocFreq()) Ciao (nomem); 
	freq->fr_Dir = dir; freq->fr_Window = win;
	freq -> fr_FuncFlags = FRF_NewWindFunc;

	ifnot (source = CreateMSource (name, NULL))	Ciao (nomem);
	ifnot (sroute = MRouteSource (source, "MidiOut", NULL))
		Ciao ("No route out");
	ifnot (dest = CreateMDest (name, NULL))		Ciao (nomem);
	ifnot (droute = MRouteDest ("MidiIn", dest, &routeinfo))
		Ciao ("No route in");
	midisig = 1L<<dest->DestPort->SIGH;
	sigs = midisig | videosig;

	HelpX ();
	while (logon) {
		if (midisig == Wait (sigs)) HandleMIDI();
		else CheckTui ();
	}
	Ciao (NULL);
}

HandleMIDI () {
	register long i;

	if (packet = GetMidiPacket (dest)) {
		xlen = packet->Length;
		if (xlen < XBUFSIZE)
			for (i=0; i<xlen; i++) xbuffer[i]=packet->MidiMsg[i];
		else {
			SPrintf (ret, "Buffer too small for %ld bytes.", xlen);
			Say (ret);
			xlen = 0;
		}
		FreeMidiPacket	(packet);
		SPrintf (ret, "%ld bytes received.", xlen);
		Say (ret);
	}
}

HitaKey	(raw)
ULONG	raw; {
	static	FLAG ctrl = NO;
	register UBYTE z;

	z = raw & 0x7f;
	if (z == 99) { 
		if (raw & 0x80) ctrl=NO;
		else ctrl=YES;
		return;
	}
	if (ctrl) switch (raw) {
		case 16:/* Q */ logon = NO;
	} else if (z == raw) {
		switch (raw) {
			case 20:/* T */ Transmit();	break;
			case 51:/* C */ CheckX();	break;
			case 40:/* L */ LoadAs();	break;
			case 33:/* S */ SaveAs();	break;
			case 69:/*ESC*/ logon = NO;
			case 68:/*RET*/ HelpX ();
		}
		spool = NO;
	}
}

LoadIt() {	xlen = Load (file, xbuffer,(long) XBUFSIZE);	}
SaveIt() {	if (xlen) Save (file, xbuffer,(long) xlen);	}
LogOut() {	logon = NO;	}
HandleEvent() {}	/* no gadgets */
Transmit () {
	if (xlen) SendMIDI ("sysx buffer", xbuffer, xlen);
	else Say ("*yawn*");
}

long SendMIDI (inf, buf, len)
 char	*inf;
 UBYTE	*buf;
 long	len;	{
	register long r;

	if (inf) {
		SPrintf (ret, "Sending %s: %ld bytes.", inf, len);
		Say (ret);
	}
	PutMidiMsg (source, xbuffer);
	if (inf) Say ("sent.");
}

#define	ZOTARK	15
CheckX () {
	register UBYTE n;
	register long i, j;
	UBYTE	line[16];

	if (xlen) {
		spool = YES;
		Say ("dump buffer:");
		for (i=0; i<xlen; i++) {
			n = xbuffer[i];
			SPrintf (ret, " %s", C2X(n)); SayMore (ret);
			j = i & ZOTARK;
			if (n<32 || (n>127 && n<160)) n = '.';
			line[j] = n;
			if (j==ZOTARK) {
				SPrintf (ret, " \xab %s \xbb",line);
				Say (ret); CheckTui(); if (!spool) break;
			}
		}
		Say (".");
	}
	else Say ("*yawn*");
}

HelpX () {
	Say (" [L]oad into buffer.");
	Say (" [T]ransmit to MIDI.");
	Say (" [S]ave to disk.");
	Say (" [C]heck buffer contents.");
	Say ("\n [ESC]ape from here!");
	Say (" [RET] type this info again.");
	Say ("\nWhatever system-exclusive data arrives");
	Say ("will be stored into buffer rightaway.");
	SPrintf (ret, "\nBuffer currently contains %ld bytes.", xlen);
	Say (ret);
}

Say (text) char *text; {
	char tmp[78];
	SPrintf (tmp, "%s\n", text); SayMore (tmp);
}
SayMore (text) char *text; {
	conreq.io_Data = (APTR) text;
	conreq.io_Length = -1;
	conreq.io_Command = CMD_WRITE;
	DoIO(&conreq);
}

Ciao (str) char *str; {
	if (cons) {
		if (str) {
			Say (str); Delay(21L);
		}
		CloseDevice (&conreq);
	}
	if (win)	CloseWindowSafely (win);
	if (droute)	DeleteMRoute	(droute);
	if (sroute)	DeleteMRoute	(sroute);
	if (dest)	DeleteMDest	(dest);
	if (source)	DeleteMSource	(source);
	if (ArpBase)	CloseLibrary	(ArpBase);
	exit (str ? 4404L : 0L);
}