home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio Version 4.94
/
audioversion4.94knowledgemediaresourcelibraryoctober1994.iso
/
amiga
/
utils
/
sonixpek
/
src
/
sonixpek.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-16
|
12KB
|
461 lines
/*
* SONIXPEEK.C by Eddy Carroll, April 1988
* ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Scans one or more Aegis Sonix music files building a list of unique
* instruments used within those files. At the end, a list of the
* instruments found is printed (can be redirected to a file if
* desired).
*
* Usage: SonixPeek {-h} {-i} {-n} {-ofile} {-xdirectory} filename ...
*
* If filename is a Sonix file, then only that file is scanned. If
* filename is a directory, then all the files in that directory which
* contain Sonix files are scanned.
*
* The -h flag suppresses the printing of the header which is normally
* present at the top of the list of instruments.
*
* If the -i (interactive) flag is present, then after each file is
* found, the user is asked whether it should be included or not when
* building the list of instruments.
*
* If the -o flag is present, then the list of instruments is stored
* in the specified file, rather than being displayed on the screen.
*
* If the -x flag is present, then the output is given in the form
* of an executable file which consists of a line for each instrument
* found of the form COPY <instrument> TO <directory>, where <directory>
* is given immediately after the -x switch.
*
* If the -n flag is present, then the list of instruments found in each
* file, when a directory is being searched, is not printed.
*
* DISTRIBUTION
* I retain copyright to the source and executable code for SonixPeek, but
* it may be freely redistributed as long as no profit is made from it.
*
* Compiles under Lattice C V4.0
*
* Note: Some of this code is messy. Have patience with it :-)
*
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <string.h>
/* The following is a quick hack to avoid having to link with lc.lib */
#define strcat(p,q) (strcpy((p)+strlen(p),(q)))
/*
* New handler for Ctrl-C. Checks if CTRL-C received, and if it has, sets
* the global CtrlC variable to true.
*/
int CtrlC;
#define chkabort() (CtrlC |= ((SetSignal(0,0) & SIGBREAKF_CTRL_C)))
#define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) + 'a' - 'A' : (c))
#define EOL '\012'
#define EOF '\037'
#define TAB '\011'
#define CR '\015'
#define MAXINS 1000 /* Only 200 instruments allowed */
#define MAXFILENUM 200 /* No more than 200 scores allowed */
#define MAXSTRING 256 /* Maximum length of a string */
#define INDENT (" ") /* Amount to indent instruments by */
/* IFF ID definitions */
#define MakeID(a,b,c,d) (long)((long)(a)<<24 | (long)(b)<<16 | (c)<<8 | (d))
#define FORM MakeID('F','O','R','M')
#define SMUS MakeID('S','M','U','S')
#define NAME MakeID('N','A','M','E')
#define SNX1 MakeID('S','N','X','1')
#define INS1 MakeID('I','N','S','1')
#define TRAK MakeID('T','R','A','K')
#define roundup(a) ((a + 1L) & ~1L)
int interactive; /* TRUE if interactive selection of files */
int multi; /* TRUE if a directory specified instead of file */
int supress; /* TRUE if listing of instruments is supressed */
int noheader; /* TRUE if no header ouput at start of instr. list */
char *dirname; /* Directory to copy to for -x option */
char *suffix[] =
{".ss", ".instr"}; /* For creating 'copy' batch file */
LONG Examine(), ExNext(), Read(), Write();
BPTR Lock(), CurrentDir();
int numins; /* Current number of instruments */
int numfiles; /* Current number of files */
char *ins[MAXINS]; /* Room for 1000 instruments */
char *files[MAXFILENUM]; /* Room for 200 files */
BPTR stdin, stdout, stderr, infile, outfile;
struct FileInfoBlock myfib;
/*
* The following lets us use our own version of malloc(). The only
* additional requirements are that we open intuition.library first,
* and call FreeRemember(&memkey,TRUE) just before exiting.
*/
struct Remember *memkey; /* Used for tracking memory */
#define malloc(n) (AllocRemember(&memkey,n,0L))
struct IntuitionBase *IntuitionBase;
/*
* Output string to file. Note that if CTRL-C has been typed,
* output is suppressed.
*/
void fprint(f, s)
BPTR f;
char *s;
{
if (!CtrlC) {
Write(f, s, strlen(s));
chkabort();
}
}
/*
* Outputs 3 strings to file f (handy for printing "String" var "String")
* The strings are concatenated first to ensure that they are printed
* as a single unit, and won't be interrupted by ^C, or even just the
* user pressing space, if the output is stdout or stderr.
*/
void fprint3(f,s1,s2,s3)
BPTR f;
char *s1,*s2,*s3;
{
static char buf[MAXSTRING * 3];
strcpy(buf,s1);
strcat(buf,s2);
strcat(buf,s3);
fprint(f,buf);
}
/*
* print() and print3() are similar to fprint() and fprint3(), but
* they output directly to stderr.
*/
#define print(s) fprint(stderr,s)
#define print3(s1,s2,s3) fprint3(stderr,s1,s2,s3)
/*
* Standard exit routine for program. Deallocates resources and exits.
* If it spots CtrlC has been pressed, it prints an appropriate message.
*/
void abort(code)
int code; /* Exit code */
{
if (CtrlC)
Write(stderr,"^C\n",3); /* print() won't work when CtrlC is true */
if (outfile != stdout && outfile != NULL)
Close(outfile);
if (stderr)
Close(stderr);
if (memkey)
FreeRemember(&memkey,TRUE);
if (IntuitionBase)
CloseLibrary(IntuitionBase);
exit(code);
}
/*
* Prints help message to standard output
*/
void help()
{
fprint3(stderr,"\n\
SonixPeek Instrument Lister Copyright Eddy Carroll April 1988\n\
\n\
Usage: SonixPeek {-h} {-i} {-n} {-ofile} {-xdirectory} file ...\n\
\n\
File is the Aegis Sonix file for which the instruments are to\n","\
be listed. If it is a directory, then all the Sonix files in\n\
that directory are checked, and a sorted list of the instruments\n\
contained in all of them is prepared. The flags operate as follows:\n\
\n","\
-h Suppress output of header at start of instrument listing\n\
\n\
-i Ask user whether or not to include each score found\n\
\n\
-n Don't list instruments as they are found\n\
\n");fprint(stderr,"\
-o Redirect sorted output to named file\n\
\n\
-x Format output as an execute file which will copy all the\n\
instruments found to the named directory\n\
\n");
}
/*** Start of actual program ***/
void main(argc, argv)
int argc;
char *argv[];
{
void addinstrument(), skip(), dumpins();
char charin();
BPTR mylock, oldlock;
char *fname;
stdin = Input();
stderr = Open("*",MODE_NEWFILE);
outfile = stdout = Output();
infile = 0;
if ((IntuitionBase = OpenLibrary("intuition.library",0L)) == NULL)
abort(99);
/* Scan command line for possible switches */
for ( argv++; argc > 1 && argv[0][0] == '-'; argc--,argv++) {
switch (tolower(argv[0][1])) {
case 'h': noheader = 1;
break;
case 'i': interactive = 1;
break;
case 'n': supress = 1;
break;
case 'o': if ((outfile = Open(argv[0]+2,MODE_NEWFILE)) == 0) {
print3("Can't open file ",argv[0]+2," for output.\n");
abort(20);
}
break;
case 'x': dirname = argv[0] + 2;
break;
default: print3("Unknown option ", argv[0], " ignored.\n");
break;
}
}
/* If missing filename, or filename == '?', print instructions */
if (argc == 1 || argv[0][0] == '?') {
help();
abort(0);
}
if (argc > 2) /* More than one file specified */
multi = 1; /* so enable printing of instrument list for each file */
/*
* Now scan each of the files or directories specified, reading
* the instruments from each one, and adding them to the list.
*/
for ( ; argc > 1; argc--, argv++) {
fname = argv[0];
if ((mylock = Lock(fname, ACCESS_READ)) == 0L) {
print3("Can't open file ",fname," for input.\n");
abort(20);
}
Examine(mylock,&myfib);
if (myfib.fib_DirEntryType > 0L) {
multi = 1;
oldlock = CurrentDir(mylock);
while (chkabort(), ExNext(mylock, &myfib) && !CtrlC)
if (myfib.fib_DirEntryType < 0L)
scan(&(myfib.fib_FileName), fname);
oldlock = CurrentDir(oldlock);
} else
scan(fname,NULL);
}
dumpins();
UnLock(mylock);
abort(0);
}
/*
* Scans filename for instruments. If found, they are added to the
* list of instruments already in memory. Returns 0 for success, -1
* if invalid file. The path parameter, which may be NULL, is the
* path to be prefixed to the filename before it is stored in memory.
* Note that this may entail adding a trailing '/' to the path.
*/
int scan(filename,path)
char *filename;
char *path;
{
LONG header[3];
char instr[50], response[50], *p;
int plen, foundinstr = 0;
if ((infile = Open(filename,MODE_OLDFILE)) == 0L) {
print3("Can't open file ", filename, " for input\n");
return(-1);
}
if (Read(infile,(char *)header,8L) != 8L || header[0] != FORM) {
Close(infile);
return(-1);
}
if (Read(infile,(char *)header,4L) != 4L || header[0] != SMUS) {
Close(infile);
return(-1);
}
if (interactive) {
print3("Include file ", filename, " (CR = no)? ");
Read(stdin, response, 50L);
if (tolower(*response) != 'y')
return(-1);
} else if (multi && !supress)
fprint3(stdout, filename, ":\n", "");
while (chkabort(), Read(infile,(char *)header,8L) == 8L && !CtrlC) {
if (header[0] != INS1) {
skip(infile,header[1]);
} else {
skip(infile,4L); /* skip position of instrument parameter */
Read(infile, instr, roundup(header[1]) - 4L);
instr[header[1] - 4L] = '\0'; /* Null-terminate string */
addinstrument(instr);
foundinstr = 1;
}
}
if (multi && !supress)
fprint(stdout,"\n");
if (foundinstr) {
if (path) {
plen = strlen(path);
p = malloc(strlen(filename)+plen+2);
/* Allocate extra byte for zero terminator and for possible '/' */
strcpy(p, path);
if (plen && p[plen-1] != ':' && p[plen-1] != '/')
strcat(p,"/");
strcat(p,filename);
} else {
p = malloc(strlen(filename)+1);
strcpy(p,filename);
}
files[numfiles++] = p;
}
Close(infile);
return(0);
}
void skip(file,size)
BPTR file;
LONG size;
{
char s[256];
LONG len = 1L;
size = roundup(size);
while (chkabort(), size > 0 && len && !CtrlC) {
len = Read(file, s, (size > 256 ? 256 : size));
size -= 256;
}
}
/*
* Adds instrument of length len into list of instruments, but only
* if its not already present in the list.
*/
void addinstrument(instr)
char *instr;
{
int pos, i;
if ((pos = matchins(instr)) != -1) {
for (i = numins++; i > pos; i--)
ins[i] = ins[i-1];
ins[pos] = malloc(strlen(instr)+1);
strcpy(ins[pos], instr);
}
if (multi && !supress) {
fprint3(stdout, INDENT, instr, "\n");
}
}
/*
* Compares string p to string s, ignoring case of alpha chars.
* Returns -ve if p < s, 0 if p = s, +ve if p > s.
*/
int mystrcmp(p,s)
char *p, *s;
{
while (*p && *s && tolower(*p) == tolower(*s))
p++, s++;
return(tolower(*p) - tolower(*s));
}
/*
* Searches instrument array for a match with given instrument.
* Returns -1 if found, else position in array to insert new element.
*/
int matchins(instr)
char *instr;
{
int i, z;
for (i = 0; i < numins; i++) {
if ((z = mystrcmp(instr, ins[i])) <= 0) {
if (z)
return(i); /* If less, insert here */
else
return(-1); /* If equal, don't insert */
}
}
return (i); /* Must be at end of list, so return last item */
}
/*
* Dumps instrument list to outfile
*/
void dumpins()
{
int i, j;
if (numins == 0) {
print("No instruments found.\n");
return;
}
if (!noheader) {
fprint(outfile,";\n; Sorted list of instruments\n");
fprint(outfile, "; --------------------------\n;\n");
if (numfiles == 1)
fprint3(outfile, "; Taken from file ", files[0], "\n");
else {
fprint(outfile,"; Taken from these files:\n;\n");
for (i = 0; i < numfiles && !CtrlC; i++) {
fprint3(outfile, "; ", files[i], "\n");
}
}
fprint(outfile,";\n");
}
if (dirname)
fprint(outfile,"failat 30\n");
for (i = 0; i < numins && !CtrlC; i++) {
for (j = (dirname != 0); j >= 0 && !CtrlC; j--) {
if (dirname) {
fprint3(outfile, "copy ", ins[i], " to ");
fprint3(outfile, dirname, "\n", "");
} else
fprint3(outfile, INDENT, ins[i], "\n");
}
}
}