/*
 * $Header: bp.c,v 1.6 88/05/16 22:11:05 glenn Exp $
 */
#include <sys/file.h>
#include <stdio.h>
#include "dx7.h"

char *itop(), *basename();

int Xflag, Vflag, Tflag, Aflag, Dflag, Pflag, Cflag;
char *BankFile;
FILE *BankFp;

main(argc, argv)
char *argv[];
{
	int exclusive;

	if (argc < 2) {
		fprintf(stderr, "%s: -[adptvx] bank files...\n", argv[0]);
		exit(1);
	}

	exclusive = -1;

	argc--, argv++;
	while (argc > 0 && **argv == '-') {
		register char *cp = *argv++;
		argc--;
		while (*++cp) switch (*cp) {
			case 'a': Aflag++; exclusive++; break; /* Add a voice */
			case 'c': Cflag++; exclusive++; break; /* Create a bank */
			case 'd': Dflag++; exclusive++; break; /* Delete a voice */
			case 'p': Pflag++; exclusive++; break; /* Print a voice */
			case 't': Tflag++; exclusive++; break; /* Table of contents */
			case 'v': Vflag++; break; /* Be verbose */
			case 'x': Xflag++; exclusive++; break; /* Extract a voice */
		default:
			fprintf(stderr, "Unknown option: %c\n", *cp);
			exit(1);
		}
	}

	if (exclusive != 0) {
		fprintf(stderr, "specify only one of \"acdptx\"\n");
		exit(1);
	}

	BankFile = *argv++;

	if (Aflag) {
		DoAdditions(argv);
	} else if (Cflag) {
		DoCreation(argv);
	} else if (Dflag) {
		DoDeletions(argv);
	} else if (Pflag) {
		DoPrint(argv);
	} else if (Tflag) {
		DoContents(argv);
	} else if (Xflag) {
		DoExtract(argv);
	}

	exit(0);
}

DoAdditions(argv)
char *argv[];
{
	struct dx7bank bank;
	struct dx7voice voice;
	int i;

	bzero(&bank, sizeof(bank));
	if (access(BankFile, W_OK) == -1)
		close(creat(BankFile, 0644));

	ReadBankFile(BankFile, &bank); /* Return value doesn't matter */
	
	if (!*argv) {
		fprintf(stderr, "Must specify what voices to add\n");
		return;
	}

#define SLOTEMPTY(c) (!(c)->cv_name[0])

	while (*argv) {
		for (i = 0; i < 32; i++) {
			if (SLOTEMPTY(((struct Cdx7voice *) (bank.b_voice[i])))) {
				if (!ReadVoiceFile(*argv, &voice)) {
					fprintf(stderr, "Can't read voice '%s'\n", *argv);
					break;
				}
				printf("a - %s  %d", *argv, i + 1);
				if (Vflag)
					printf(" \"%10.10s\"", voice.v_name);
				printf("\n");
				VoiceCompress(&voice, bank.b_voice[i]);
				goto done;
			}
		}
		if (i == 32) {
			fprintf(stderr, "No room for voice\n");
			break;
		}
done:
		argv++;
	}

	if (!WriteBankFile(BankFile, &bank))
		return;
}

DoCreation(argv)
char *argv[];
{
	int fd;

	if ((fd = creat(BankFile, 0644)) < 0) {
		perror(BankFile);
		return (1);
	}
	close(fd);

	DoAdditions(argv);
}

DoDeletions(argv)
char *argv[];
{
	struct dx7bank bank;
	struct Cdx7voice *cv;
	int i;

	if (!ReadBankFile(BankFile, &bank)) {
		return (1);
	}

	if (!argv[0]) {
		fprintf(stderr, "-d requires indicies\n");
		return (1);
	}

	while (*argv) {
		i = atoi(*argv++);
		if (i < 0 || i > 32) {
			fprintf(stderr, "index not 0 < %d < 32\n", i);
			continue;
		}
		cv = (struct Cdx7voice *) bank.b_voice[i - 1];
		printf("d - %d", i);
		if (Vflag)
			printf(" \"%10.10s\"", cv->cv_name);
		printf("\n");
		bzero(cv, sizeof(*cv));
	}
	
	if (!WriteBankFile(BankFile, &bank)) {
		return (1);
	}

	return (0);
}

DoContents(argv)
char *argv[];
{
	struct dx7bank bank;
	struct Cdx7voice *cv;
	int i;

	if (!ReadBankFile(BankFile, &bank)) {
		fprintf(stderr, "%s: not a bank\n", BankFile);
		return;
	}

	if (argv[0]) {
		while (*argv) {
			i = atoi(*argv++);
			if (i < 1 || i > 32) {
				fprintf(stderr, "%d is out of range\n", i);
				continue;
			}
			cv = (struct Cdx7voice *) bank.b_voice[i - 1];
			printf("%10.10s\n", cv->cv_name);
		}
	} else {
		for (i = 0; i < 32; i++) {
			cv = (struct Cdx7voice *) bank.b_voice[i];
			printf("%10.10s\n", cv->cv_name);
		}
	}
}

DoExtract(argv)
char *argv[];
{
	char fileName[512];
	struct dx7bank bank;
	struct dx7voice voice;
	struct Cdx7voice *cv;
	int i;

	if (!ReadBankFile(BankFile, &bank)) {
		fprintf(stderr, "%s: not a bank\n", BankFile);
		return;
	}

	if (argv[0]) {
		while (*argv) {
			i = atoi(*argv++);
			if (i < 1 || i > 32) {
				fprintf(stderr, "%d is out of range\n", i);
				continue;
			}
			
			VoiceExpand(bank.b_voice[i - 1], &voice);
			sprintf(fileName, "%s.%02d", basename(BankFile), i + 1);
			printf("x - %s", fileName);
			if (Vflag)
				printf(" \"%10.10s\"", voice.v_name);
			printf("\n");
			WriteVoiceFile(fileName, &voice);
		}
	} else {
		for (i = 0; i < 32; i++) {
			VoiceExpand(bank.b_voice[i], &voice);
			sprintf(fileName, "%s.%02d", basename(BankFile), i);
			printf("x - %s", fileName);
			if (Vflag)
				printf(" \"%10.10s\"", voice.v_name);
			printf("\n");
			WriteVoiceFile(fileName, &voice);
		}
	}
}

DoPrint(argv)
char *argv[];
{
	struct dx7bank bank;

	if (!ReadBankFile(BankFile, &bank)) {
		fprintf(stderr, "%s: not a bank\n", BankFile);
		return;
	}
	
	BankPrint(&bank);
}

BankPrint(b)
struct dx7bank *b;
{
	struct Cdx7voice *c;
	struct dx7voice voice;
	int i;

	for (i = 0; i < 32; i++) {
		c = (struct Cdx7voice *) b->b_voice[i];
		VoiceExpand(b->b_voice[i], &voice);
		if (i == 32)
			printf("***\n");
		PrintVoice(&voice);
		printf("\n\n");
	}

}
