/* simplified receive system exclusive */
/*    receives next sys/ex message and save it to a named file */

/*
    shows usage of GetMidiPacket(), FreeMidiPacket() 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 */
    struct MidiPacket *packet=0, *getpacket();
    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 (UNIX vanilla mode) */
    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 (packet = getpacket(dest)) {
	if (write (fo,packet->MidiMsg,packet->Length) != packet->Length ||
	    close(fo) == -1) {
		printf ("error writing file.\n");
	}
	printf ("sys/ex file \"%s\" saved. (%d bytes)\n",fname,packet->Length);
    }
    else {
	printf ("save aborted.\n");
	close(fo);
	unlink(fname);
    }

clean:
    if (packet) FreeMidiPacket (packet);
    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
*/

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

    if (Wait(flags) & SIGBREAKF_CTRL_C) return NULL;
    return GetMidiPacket (dest);
}
