#include <stdio.h>
#include <midi.h>
#include <dx7voice.h>

#d e MidiError

Error(s) { e("%s: ", av0); perror(s); exit(1); }

#d inrange(l,x,h) ((l) <= (x) && (x) <= h)
#d Dchannel 0
int channel = Dchannel;	/* which channel to suck from */

suck(fd,n,f) FILE *f; {
	Dx7Voice *dx7GetVoice(), *v;
	if (n<0 || n>31) return e("%s: invalid voice number (%d)\n",av0,n);
	v = dx7GetVoice(fd,channel,n);
	if (!v) return e("%s: couldn't get voice %d\n",n);
	dx7writeVoice(v,f);
}

use(){
  e("Use: %s [-c channel] [-C] [voices]\n",av0);
  e(" -c #  read voices from midi channel # (1-16, %d)\n", Dchannel+1);
  e(" -C #  read cartridge (not internal) voices\n", Dchannel+1);
  e("'voices' are dx7 voice numbers, 1-32:\n");
  e("  if 1 voice is given, it is written to stdout\n");
  e("  if >1 voice is given, files called 'voice.nnn' are created\n");
  e("  if no voices given, all are written out\n");
  e("Example:\n");
  e("  %s -C 1 > flute\n",av0);
  e("reads voice 1 from cartridge into 'flute'\n");
  exit(1);
}

main(ac, av)
	char **av;
/*
** use: vget [n]
** sucks voice n out of the dx7, writes it to stdout.
** if more than 1 voice given, e.g.,
**	suck 1 2 3 4 5 6 7 8
** writes each to "voice.n" where 'n' is the number.
** with no arguments
**	suck
** means
**	suck 1 2 3 ... 31
** note that 'n' is 1-based (ie, 'suck 1' gets you the voice
** under button number 1.
*/
{
	char buf[BUFSIZ];
	Int i, midi, n, cartridge=0;
	FILE *f, *fopen();
	char s[500];
#define Voice(n) sprintf(s,"voice.%d",(n)+1)

	for_each_argument {
	Case 'c': channel=atoi(argument)-1; if (!inrange(0,channel,15)) use();
	Case 'C': cartridge = 1;
	Default : use();
	}

	if ((midi = open(MidiDevice, 2)) == -1) Error(MidiDevice);
	MpuSend(midi,
		MPU_RESET,
		MPU_EXCLUSIVE_TO_HOST_ON,
		0);
	dx7SysInfoAvail(midi,channel,1);   /* must have sys info avail */
	dx7MemSelect(midi,channel,cartridge);

		/* for some reason, getting an initial extraneous voice
		** seems to unclog something important.  this is a stinky
		** hack, due to some driver anomaly.
		*/
	dx7GetVoice(midi,channel,0);

	if (ac==1 || (ac==2 && strcmp(av[1],"all")==0))
		for (i=0;i<32;i++){
			f = fopen(Voice(i),"w");
			if (f) suck(midi,i,f), fclose(f);
			else perror(Voice(i));
		}
	else if ((ac-i)==1) suck(midi,atoi(av[i])-1,stdout);
	else for (;i<ac;i++)
		if (f = fopen(Voice(n=atoi(av[i])-1),"w"))
			suck(midi,n,f), fclose(f);
		else perror(s);
	exit(0);
}
