/* 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);
}
