/*	lsf.c -- list SPARC/NeXT format sound files
 *		stp - 5/89, 2/92
 *
 * 	output example:
 *  NAME               RATE   CHLS  FORMAT    DURATION  TYPE
 *  l1.src.snd         44100  1     Lin-16 	  42.632    IRCAM
 *		source sound of low bell
 *			---comment lines---
 *			
 *	can be executed as lsf, lsfl (implicit '-l' option), or
 *		lsfc (implicit '-c')
 */
#include <stdio.h>
#include <errno.h>
#include "NeXTsfheader.h"		/* merged NeXT/IRCAM header */
#include <sys/file.h>
#include "../cmix/H/ugens.h"
#include <sys/types.h>
#include <sys/dir.h>
#include <strings.h>

int longList, comment;

static SFCODE ampcode = {
	SF_MAXAMP, sizeof(SFMAXAMP) + sizeof(SFCODE)
}; 

static SFCODE commentcode = {
	SF_COMMENT, MINCOMM + sizeof(SFCODE)
};

SFHEADER sfh;
SFMAXAMP sfm;
SFCOMMENT sfcm;

#define TITLE_FORMAT "NAME               RATE   CHLS  FORMAT    DURATION  TYPE\n"

main(argc, argv) int argc; char *argv[]; {
	int i, fd, argCount=1;
	FILE *fp;
	DIR *directory;
	struct direct *fptr;
	char *name, *pos;
	
	longList=0;
	comment=0;
	if (!strcmp(argv[0], "lsfl")) {		/* if the user typed 'lsfl'	*/
		longList = 1;
		printf (TITLE_FORMAT);
	}
	if (!strcmp(argv[0], "lsfc")) {		/* if the user typed 'lsfl'	*/
		longList = 1;
		comment = 1;
		printf (TITLE_FORMAT);
	}
	for (i=1; i<argc; i++) {
		if (!strcmp(argv[i], "-u")) {
			fprintf(stderr, 
				"\n\n\tlsf/lsfl/lsfc [-l -c] [ file(s) ]\n\n");
			exit(0);
		}
		if (!strcmp(argv[i], "-l")) {
			longList = 1;
			argCount++;
			printf (TITLE_FORMAT);
		}
		if (!strcmp(argv[i], "-c")) {
			longList = 1;
			comment = 1;
			printf (TITLE_FORMAT);
			argCount++;
	}}
				/* if the user said 'lsf' without any file names */
	if(argCount == argc) {	
		directory = opendir(".");
		for (fptr = readdir(directory);  fptr != NULL;  
					fptr = readdir(directory)) {
			if (fptr->d_namlen > 4) {
				name = fptr->d_name;
				pos = rindex(name, '.');
				if (pos != NULL) {
					if (!strncmp(pos, ".snd", 4))
						listSoundFile (name);
		}}}
	} else			/* if the user gave some filenames in argv[] */
		for (i=argCount; i<argc; i++)
			listSoundFile (argv[i]);
	if(!longList) 
		printf("\n");
}		/* main	*/


/* 
 *	procedure to list a given soundfile name
		NAME		RATE	CHLS	FORMAT		  DURATION
 */
#define MAXLEN 18
listSoundFile (sfName) char *sfName; {
	int i, sf, result;
	struct stat sfst;
	char *listFormat(), shortName[MAXLEN+1], msg[64], *baseName;
	
	readopensf(sfName, sf, sfh, sfst, "lsf", result)
	if(result < 0) return;
	if (!ismagic(&sfh)) {
		fprintf(stderr, "lsf: '%s' is not a soundfile\n", sfName);
		close(sf);
		return;
	}
	if (!longList) {				/* short version	*/
		printf("%s\t\t", sfName);
	} else {				/* long version	*/
		baseName = rindex(sfName, '/');
		if (baseName == NULL)
			baseName = sfName-1;
		if (strlen(baseName) > MAXLEN) {
			strncpy(shortName, baseName+1, MAXLEN);
			shortName[MAXLEN] = '\0';
			printf("%s", shortName);
		} else
			printf("%-18s", baseName+1);
		printf(" %d  %d     ", nsfrate(&sfh), nsfchans(&sfh));
		printf("%s \t%8.3f    %s\n", (listFormat(nsfformat(&sfh))),
			((float)nsfdsize(&sfh) / (nsfrate(&sfh) * nsfchans(&sfh) * 2)),
			(nsfhsize(&sfh) == 28 ? "NeXT" : "IRCAM"));
		if (comment)
			printComment(&sfh);
	}
	close(sf);
}


/*
 * printComment--procedure to print out soundfile comments
 */
printComment(head) SFHEADER *head; {
	SFMAXAMP sfm;
	SFCODE *sizer;
	SFCOMMENT sfcm;
	char *cp, *getsfcode();
	char date[26];
	int i;

	cp = getsfcode(head, SF_MAXAMP);
	bcopy(cp + sizeof(SFCODE), (char *)&sfm, sizeof(SFMAXAMP));
	if(cp != NULL) {
		for(i=0; i<sfchans(head); i++)
			if(sfmaxamp(&sfm, i) != 0.0)
				printf("\tchannel %d  maxamp: %ld  at: %ld\n",
					i, (long)(sfmaxamp(&sfm, i)), (long)(sfmaxamploc(&sfm, i)));
		cp = getsfcode(head, SF_COMMENT);
/*		if(sfmaxamptime(&sfm)) {
			strcpy(date, ctime(&sfmaxamptime(&sfm)));
			printf("date=%s\n", date);
		}
*/
	}
	if(cp != NULL) {
		sizer = (SFCODE *) cp;
		bcopy(cp + sizeof(SFCODE), (char *)&sfcm, sizer->bsize);
		if (strlen(&sfcomm(&sfcm, 0)) > 0)
			printf("\t%s\n", &sfcomm(&sfcm, 0));
}}


/*
 *	listFormat--procedure to print out format type
 */
char *listFormat (type) int type; {

	switch (type) {
		case 0:
			return (" ??   ");
		case 1:
			return ("Mu-8  ");
		case 2:
			return ("Lin-8 ");
		case 3:
			return ("Lin-16");
		case 4:
			return ("Lin-24");
		case 5:
			return ("Lin-32");
		case 6:
			return ("Flo-32");
		case 7:
			return ("Flo-64");
		case  8:
			return (" Ind  ");
		case  9:
			return ("Nested");
		case  10:
		case  11:
		case  12:
		case  13:
		case  14:
			return ("DSP   ");
	}
	return ("Wierd");
}

