
/*
 * ssamp.c - send one sample header + sample to the sampler
 *
 * Copyright (c) 2002-2004 Frank Neumann <franky@users.sourceforge.net>
 *
 */

/*** INCLUDES ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "lakai.h"

/*** DEFINES ***/
/* This is fixed for data coming from an S2000; S1000 would have smaller values here */
#define HEADERLEN 192
#define MAXLINE 256
#define MAX_SAMPLENUM 255
#define MAX_PROGNUM   254

/*** PROTOTYPES ***/
int do_send_sample(LHANDLE hd1, char *fname, int sample_idx);
int do_send_program(LHANDLE hd1, char *fname, int prog_idx);



/*** BEGIN OF MAIN ***/
int main(int argc, char *argv[])
{
	int sample_idx, prog_idx;
	FILE *lfp;
	unsigned char linebuf[MAXLINE], fname[256];
	LHANDLE hd1;

	
	if (argc != 3 )
	{
		fprintf(stderr, "Usage: %s <devname> <listfile>\n", argv[0]);
		exit(1);
	}

	lakai_init();

	hd1 = lakai_open(argv[1]);
	if (hd1 < 0)
	{
		fprintf(stderr, "Open failed.\n");
		exit(5);
	}

	lfp = fopen(argv[2], "r");
	if (!lfp)
	{
		fprintf(stderr, "Unable to open list file '%s' for reading\n", argv[2]);
		lakai_close(hd1);
		exit(5);
	}

	sample_idx = 0;
	prog_idx = 0;

	while(fgets(linebuf, MAXLINE, lfp) != NULL)
	{
//		fprintf(stderr, "Line: '%s'\n", linebuf);

		/* empty lines: ignored */
		if (linebuf[0] == 0x0a || linebuf[0] == 0x0d)
			;
		/* comment lines: ignored */
		else if (linebuf[0] == '#')
			;
		else if (strncmp(linebuf, "SAMP ", 5) == 0)
		{
			sscanf(linebuf+5, "%s", fname);
			do_send_sample(hd1, fname, sample_idx++);
		}
		else if (strncmp(linebuf, "PROG ", 5) == 0)
		{
			sscanf(linebuf+5, "%s", fname);
			do_send_program(hd1, fname, prog_idx++);
		}
		else
			fprintf(stderr, "ignored unknown listfile line: %s", linebuf);
	} 
	
	/* delete the very first program (the one that "always exists") */
	lakai_delete_program(hd1, 0);
		
	lakai_setmode(hd1, LAKAI_MODE_NORMAL);
	lakai_close(hd1);
	fclose(lfp);
	exit(0);
}


/*
 * do_send_sample(): Send a single sample to sampler
 *
 * INPUTS:
 * 	LHANDLE hd1: handle to lakai device
 * 	char *fname: filename of file to send to sampler
 * OUTPUTS:
 * 	int: 1 if send was ok, 0 otherwise.
 */
int do_send_sample(LHANDLE hd1, char *fname, int sample_idx)
{
	FILE *fp1;
	int flen, res;
	unsigned char *buf;
	unsigned long slocat;
	unsigned char hdrbuf[1024];

//	fprintf(stderr, "Sending sample from file '%s'\n", fname);

	fp1 = fopen(fname, "r");
	if (!fp1)
	{
		fprintf(stderr, "do_send_sample(): Could not open program file '%s'\n", fname);
		return 0;
	}
	fseek(fp1, 0, SEEK_END);
	flen = ftell(fp1),
	fseek(fp1, 0, SEEK_SET);
	buf = malloc(flen);
	if (!buf)
	{
		fprintf(stderr, "do_send_sample(): Unable to malloc sample buf\n");
		fclose(fp1);
		return 0;
	}

	fprintf(stderr, "Uploading sample #%d from file '%s', %d bytes...", sample_idx, fname, flen);
	fread(buf, flen, 1, fp1);
	fclose(fp1);
	
	/* send sample header ... */
//	fprintf(stderr, "Creating new sample header...");
	/* 255 is a the highest possible  sample number  so we can be somewhat sure we 
	 * create a new sample this way */
	lakai_put_sample_header(hd1, MAX_SAMPLENUM, buf, 192);
//	fprintf(stderr, "Done.\n");

	/* determine where the sampler allocated the memory for this sample */
//	fprintf(stderr, "Requesting sample header data...");
	res = lakai_get_sample_header(hd1, sample_idx, hdrbuf);
//	fprintf(stderr, "Done.\n");
//	fprintf(stderr, "Location of this sample in mem: $%x\n", lsh.slocat);

	slocat = hdrbuf[25] * 16777216 + hdrbuf[24] * 65536 + hdrbuf[23] * 256 + hdrbuf[22];
//	fprintf(stderr, "Sample mem allocated at $%p\n", (void *)slocat);

	/* It appears like there can be no "holes" between sample
	 * numbers, and they are numbered sequentially, starting with 0, in order of their
	 * creation. So, to bind sample numbers to sample names, the user has to keep track
	 * of what sample headers were uploaded when - or he just has to get the whole
	 * list again through lakai_get_sample_list().
	 */

	/* send sample data.. */
//	fprintf(stderr, "Uploading PCM data..\n");
	lakai_put_sample(hd1, sample_idx, buf+192, 0, flen-192);
//	lakai_put_sample(hd1, sample_idx, buf+192, slocat, flen-192);
	fprintf(stderr, "done.\n");

	free(buf);
	return 1;
}


/*
 * do_send_program(): Sends a single program (and its keygroups) to sampler
 *
 * INPUTS:
 * 	LHANDLE hd1: handle to lakai device
 * 	char *fname: filename of file to send to sampler
 * OUTPUTS:
 * 	int: 1 if send was ok, 0 otherwise.
 */
int do_send_program(LHANDLE hd1, char *fname, int prog_idx)
{
	FILE *fp1;
	int i, flen, numkeygroups;
	unsigned char *buf;
	
	fp1 = fopen(fname, "r");
	if (!fp1)
	{
		fprintf(stderr, "do_send_program(): Could not open program file '%s'\n", fname);
		return 0;
	}
	fseek(fp1, 0, SEEK_END);
	flen = ftell(fp1),
	fseek(fp1, 0, SEEK_SET);
	buf = malloc(flen);
	if (!buf)
	{
		fprintf(stderr, "do_send_program(): Unable to malloc program buf\n");
		fclose(fp1);
		return 0;
	}

	fread(buf, flen, 1, fp1);
	fclose(fp1);

	numkeygroups = buf[42];
	fprintf(stderr, "Uploading program #%d from file '%s', %d keygroup(s)...\n", prog_idx, fname, 
			numkeygroups);

	/* TODO: Test: set to 0 first.. */
	buf[42] = 1;
	
	/* first, send the program with "empty" keygroups" */
	lakai_put_program(hd1, MAX_PROGNUM, buf, 192);

//	fprintf(stderr, "%d keygroups in this program; sending now..", numkeygroups);
		
	/* then, send the keygroups for this program */
	for (i = 0; i < numkeygroups; i++)
	{
		/* 255 is the indicator for "create keygroup in previously sent program" */
		fprintf(stderr, "\tUploading keygroup %d..", i);
		/* TODO: Testing... */
		lakai_put_keygroup(hd1, prog_idx+1, i, buf+(i+1)*192, 192);
//		lakai_put_keygroup(hd1, 255, i, buf+(i+1)*192, 192);
		fprintf(stderr, "done.\n");
	}
	
//	fprintf(stderr, "done.\n");
	free(buf);
	
	return 1;
}

