/*
 * A sample program which dumps a Kawai K4 sysex dump to the
 * midi line.
 * Any incoming character aborts the dump.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/soundcard.h>

#define BUFLEN 1024
#define MIDI_DEVICE_NUMBER	2	/* The third midi card in the system */
int fd;

main (int argc, char *argv[])
{
  unsigned char buf[BUFLEN], obuf[4 * BUFLEN] =
  {0};
  int i, tmp, n, p;

  if ((fd = open ("/dev/sequencer", O_RDWR, 0)) == -1)
    {
      perror ("/dev/sequencer");
      exit (-1);
    }

  while ((n = read (0, buf, BUFLEN)) > 0)
    {
      p = 0;

      for (i = 0; i < n; i++)
	{
	  obuf[p + 0] = SEQ_MIDIPUTC;
	  obuf[p + 1] = buf[i];
	  obuf[p + 2] = MIDI_DEVICE_NUMBER;
	  obuf[p + 3] = 0;
	  p += 4;
	}

      if (write (fd, obuf, p) != p)
      {
      	printf("/dev/sequencer: Write error\n");
      	exit(-1);
      }

      if (buf[n - 1] == 0xf7)
	finished ();

      ioctl (fd, SNDCTL_SEQ_GETINCOUNT, &n);

      if (n>0)
	{
	  printf ("Interrupted by incoming midi byte\n");
	  finished ();
	}
    }

  fprintf (stderr, "Unexpected EOF\n");
}

int
die (char *s)
{
  printf ("%s", s);
  exit (-1);
}

int
finished ()
{
  int i, n;
  unsigned char buf[4];

  unsigned char reply[100];
  int replyp = 0;

  printf ("Ready\n");

  while (1)
    {
      ioctl (fd, SNDCTL_SEQ_GETINCOUNT, &n);
      if (n>0)
	for (i = 0; i < n; i++)
	  {
	    read (fd, buf, 4);

#ifdef INTERPRET_TIME
	    if (buf[0] == SEQ_WAIT)	/* Timestamp message */
	    {
	    	int time = *(int*)&buf[0] >> 8;
	    	printf("Time: %d\n", time);
	    }
#endif

	    if (buf[0] == SEQ_MIDIPUTC)
	      {
		if (replyp < 100)
		  reply[replyp++] = buf[1];

		printf ("%02x ", buf[1]);
		fflush (stdout);
		if (buf[1] == 0xf7)
		  {
		    printf ("\n");

		    if (reply[0] != 0xf0)
		      die ("Not sysex\n");
		    if (reply[1] != 0x40)
		      die ("Not Kawai sysex\n");
		    if (reply[2] != 0x00)
		      die ("Wrong reply channel\n");
		    if (reply[4] != 0x00)
		      die ("Kawai: Not a synthesizer\n");
		    if (reply[5] != 0x04)
		      die ("Kawai: Not K4/K4r\n");

		    if (reply[3] != 0x40)
		      {
			if (reply[3] == 0x41)
			  die ("Kawai: Write error\n");
			if (reply[3] == 0x42)
			  die ("Kawai: Write protect error\n");
			if (reply[3] == 0x42)
			  die ("Kawai: No card\n");
			die ("Kawai: Unknown error\n");
		      }
		    printf ("Uploaded OK\n");
		    exit (0);
		  }
	      }
	  }
    }
}
