home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.6
/
ffcollection-1-6-1993-02.iso
/
ff_disks
/
211-240
/
ff_228
/
glib
/
glib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-26
|
29KB
|
1,473 lines
/*
* GLIB - a Generic LIBrarian and editor for synths
*/
#include "glib.h"
#include <ctype.h>
char *Reason = "";
int Currrow = 0; /* at top of screen, for messages */
int Libbank = 0; /* from 0 to LIBBANKS-1, is the current library bank*/
int Nsynths = 0;
char *Currdata;
char *Yankdata; /* current 'yank' buffer (middle of screen) */
struct peredinfo *PE; /* array of per-editor miscellany */
char Buff[BUFSIZ];
int Redraw = 0; /* if non-0, edit screen is completely redrawn. */
/* parameter functions can make use of this. */
int Changed = 0;
/* All the global values below are set as appropriate for the */
/* synthesizer currently being dealt with. */
int Nvoices = 0;
int Voicesize =0;
int Namesize = 0;
int Libindex; /* from 0 to Nvoices-1 */
int Synindex; /* from 0 to Nvoices-1 */
int Channel;
int Editrow; /* from 0 to NUMONSCREEN-1 */
int Editcol; /* 0==synth, 1==library */
char *Libdata; /* current library data (includes all LIBBANKS) */
/* ie. the stuff on the right side of the screen */
char *Syndata; /* current synth data (1 bank), ie. the left side */
struct paraminfo *P; /* list of parameter info */
struct labelinfo *L; /* arbitrary screen labels for edit screen */
char *Synthname;
int (*Sendedit)(); /* function to send parameters to synth's edit buffer*/
int (*Datain)(); /* convert data from file-storage format to the */
/* format stored in the P[] parameter array (p_val) */
int (*Dataout)(); /* reverse of Datain */
int (*Sendone)(); /* function to send one (permanent) voice to synth */
int (*Sendbulk)(); /* function to send bulk dump to synth */
int (*Getbulk)(); /* reverse of Sendbulk */
char *(*Nameof)(); /* pulls voice name out of file-storage data */
int (*Setnameof)(); /* reverse of Nameof */
char *(*Numof)(); /* convert voice number to on-screen text */
int (*Cvtnum)(); /* convert visible voice number to std. format */
int (*Cvtanum)(); /* convert alphanumeric voice number to std. format */
/* should never define both Cvtnum and Cvtanum */
main()
{
int n;
hello();
windinit();
initstuff();
if ( Nsynths == 0 )
windstr("Hey, the E array is empty?");
else if ( Nsynths == 1 ) {
/* If there's only 1 synth, don't bother asking */
setedit(0);
libinteract();
}
else {
while ( (n=choosesynth()) >= 0 ) {
setedit(n);
libinteract();
unsetedit(n);
}
}
bye();
}
/* choose a synth, returning its position in the E array */
choosesynth()
{
int n, pick;
retry:
flushconsole();
windclear();
windgoto(2,18);
windstr("GLIB - A Generic Librarian/Editor");
for ( n=1; n<=Nsynths; n++ )
libchoice(n);
windgoto(10+n,16);
windstr("Choose your synth (or 'q' to quit) --> ");
windrefresh();
pick = mouseorkey();
if ( pick == 'q' || pick == EOF )
return(-1);
if ( pick != MOUSE )
pick = pick - '0';
else {
int row, col;
getmouse(&row,&col);
/* wait until mouse goes down */
while ( statmouse() > 0 )
;
pick = row - 6;
}
if ( pick < 1 || pick > Nsynths )
goto retry;
return(pick-1);
}
libchoice(n)
{
windgoto(6+n,27);
sprintf(Buff,"%d - %s",n,E[n-1].ed_name);
windstr(Buff);
}
initstuff()
{
int n, banksize, maxvsize = 0;
char *p;
for ( n=0; E[n].ed_name != NULL; n++ ) {
if ( maxvsize < E[n].ed_vsize )
maxvsize = E[n].ed_vsize;
}
Nsynths = n;
Currdata = alloc( maxvsize );
/* allocate an array of peredinfo structs */
PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo)));
for ( n=0; n<Nsynths; n++ ) {
banksize = E[n].ed_nvoices * E[n].ed_vsize;
p = PE[n].ed_libdata = alloc( LIBBANKS * banksize );
clrdata(p,LIBBANKS*banksize);
p = PE[n].ed_syndata = alloc( banksize );
clrdata(p,banksize);
p = PE[n].ed_yankdata = alloc( E[n].ed_vsize );
clrdata(p,E[n].ed_vsize);
PE[n].ed_libindex = 0;
PE[n].ed_synindex = 0;
PE[n].ed_channel = 1;
PE[n].ed_erow = 0;
PE[n].ed_ecol = 0;
}
}
clrdata(data,size)
char *data;
{
register char *p = data, *endp = data+size;
while ( p<endp )
*p++ = 0;
}
setedit(n)
{
Synthname = E[n].ed_name;
Datain = E[n].ed_din;
Dataout = E[n].ed_dout;
Nvoices = E[n].ed_nvoices;
Sendedit = E[n].ed_sedit;
Sendone = E[n].ed_sone;
Sendbulk = E[n].ed_sbulk;
Getbulk = E[n].ed_gbulk;
Nameof = E[n].ed_nof;
Numof = E[n].ed_numof;
Cvtnum = E[n].ed_cvtnum;
Cvtanum = E[n].ed_cvtanum;
Setnameof = E[n].ed_snof;
Voicesize = E[n].ed_vsize;
Namesize = E[n].ed_nsize;
Libdata = PE[n].ed_libdata;
Syndata = PE[n].ed_syndata;
Yankdata = PE[n].ed_yankdata;
Libindex = PE[n].ed_libindex;
Synindex = PE[n].ed_synindex;
Channel = PE[n].ed_channel;
Editrow = PE[n].ed_erow;
Editcol = PE[n].ed_ecol;
clrdata(Currdata,Voicesize);
P = E[n].ed_params;
L = E[n].ed_labels;
}
unsetedit(n)
{
int k;
PE[n].ed_libindex = Libindex;
PE[n].ed_synindex = Synindex;
PE[n].ed_channel = Channel;
PE[n].ed_erow = Editrow;
PE[n].ed_ecol = Editcol;
for ( k=0; k<Voicesize; k++ )
PE[n].ed_yankdata[k] = Yankdata[k];
}
/* template - show the boxes and such on the main library screen */
template()
{
int n, k, r;
r = FIRSTROW-1;
sprintf(Buff,"%s Voices",Synthname);
n = 13 - strlen(Buff)/2; /* center it */
windgoto(r,n<0?0:n);
windstr(Buff);
r++;
windgoto(r,0);
for ( n=0; n<26; n++ )
windputc('=');
windgoto(r,52);
for ( n=0; n<26; n++ )
windputc('=');
for ( n=r+1; n<(r+13); n++ ) {
windgoto(n,0);
windputc('|');
windgoto(n,6);
windputc('|');
windgoto(n,25);
windputc('|');
k=52;
windgoto(n,k);
windputc('|');
windgoto(n,k+6);
windputc('|');
windgoto(n,k+25);
windputc('|');
}
windgoto(r+13,0);
for ( n=0; n<26; n++ )
windputc('=');
windgoto(r+13,52);
for ( n=0; n<26; n++ )
windputc('=');
windgoto(YANKROW-2,YANKCOL);
windstr(" Yank Buffer");
windgoto(YANKROW-1,YANKCOL);
windstr(" ------------- ");
windgoto(YANKROW,YANKCOL);
windstr(" ");
windgoto(YANKROW+1,YANKCOL);
windstr(" ------------- ");
windrefresh();
}
/* clear the message area */
clearmess()
{
int n;
for(n=1;n<(FIRSTROW-1);n++)
winderaserow(n);
Currrow = 0;
}
/* set the current voice (ie. the synth's edit buffer) to the indicated */
/* voice. c==0 is the synth (left) side, c==1 is the library (right) side. */
editto(r,c)
{
int voicenum;
/* Clear the existing '*' */
editchar(' ',Editrow,Editcol);
editchar('*',Editrow=r,Editcol=c);
if ( Editcol==0 ) {
/* we're on the synth side */
voicenum = Editrow+Synindex;
tocurrent(Syndata,voicenum);
}
else {
/* we're on the lib side */
voicenum = Editrow+Libindex;
tocurrent(bankvoice(0),voicenum);
}
}
editchar(ec,r,c)
{
r = r + FIRSTROW + 1;
if ( c == 0 )
c = LEFTSIDE-1;
else
c = RIGHTSIDE-1;
windgoto(r,c);
windputc(ec);
windrefresh();
}
/* control interaction on the main library bank screen */
libinteract()
{
int c, n, swap, voicenum, maxindex;
char *p, *data;
flushmidi();
drawall();
for ( ;; ) {
Currrow = 0;
winderaserow(Currrow);
windgoto(Currrow,0);
windstr("Command --> ");
windrefresh();
c = mouseorkey();
if ( c == MOUSE ) {
libmouse();
continue;
}
if ( isprint(c) )
windputc(c);
clearmess();
switch ( c ) {
case ' ':
playnote(1);
break;
case '\n':
#ifndef macintosh
case '\r':
#endif
/* ignore */
break;
case EOF:
case 'q':
return;
case CH_REDRAW:
drawall();
break;
case 's':
case 'p':
swap = (c=='s')?1:0;
if ( Editcol==0 )
tosyn(Synindex+Editrow,Yankdata,swap);
else
tolib(Libindex+Editrow,Yankdata,swap);
updatedisplay();
pryankname();
break;
case 'y':
for(n=0;n<Voicesize;n++)
Yankdata[n] = Currdata[n];
pryankname();
break;
case '?':
helpmessage();
break;
case SCR_DOWN:
maxindex = Nvoices - NUMONSCREEN;
if ( Editcol==0 ) {
/* we're on the synth side */
if ( (Synindex+=NUMONSCREEN/2) > maxindex )
Synindex = maxindex;
}
else {
/* we're on the lib side */
if ( (Libindex+=NUMONSCREEN/2) > maxindex )
Libindex = maxindex;
}
updatedisplay();
break;
case SCR_UP:
if ( Editcol==0 ) {
/* we're on the synth side */
if ( (Synindex-=NUMONSCREEN/2) < 0 )
Synindex = 0;
}
else {
/* we're on the lib side */
if ( (Libindex-=NUMONSCREEN/2) < 0 )
Libindex = 0;
}
updatedisplay();
break;
case '\033':
case '`':
allnotesoff();
break;
case 't':
transcmd();
break;
case 'd': /* download from synth to display */
clrdata(Syndata,Nvoices*Voicesize);
if ( readsynth(Syndata) == 0 )
syntodisplay(Synindex=0);
break;
case 'u': /* upload TO synth */
if ( Editcol==0 ) {
voicenum = Editrow+Synindex;
data = &(VOICEBYTE(Syndata,voicenum,0));
}
else
data = bankvoice(Editrow+Libindex);
upload(data);
break;
case 'r':
readall();
break;
case 'w':
writeall();
break;
case 'c':
setchan();
break;
case 'b':
/* cycle through banks, from 0 to LIBBANKS-1 */
if ( ++Libbank >= LIBBANKS )
Libbank = 0;
libtodisplay(Libindex);
updatedisplay();
break;
case 'e':
p = (*Nameof)(Currdata);
if ( Editcol==0 ) {
voicenum = Editrow+Synindex;
data = &(VOICEBYTE(Syndata,voicenum,0));
editdata(p,data);
windclear();
/* Update Currdata */
for ( n=0; n<Voicesize; n++ )
Currdata[n] = VOICEBYTE(Syndata,voicenum,n);
}
else {
data = bankvoice(Editrow+Libindex);
editdata(p,data);
}
drawall();
break;
case 'g': /* goto a specific voice */
do_goto();
break;
case CH_LEFT:
if ( Editcol==1 )
editto(Editrow,0);
break;
case CH_DOWN:
if ( Editrow < (NUMONSCREEN-1) )
editto(Editrow+1,Editcol);
else {
/* we're at the bottom, so try to scroll */
if ( Editcol==0 ) {
/* we're on the synth side */
if (Synindex<(Nvoices-NUMONSCREEN))
Synindex++;
}
else {
/* we're on the lib side */
if (Libindex<(Nvoices-NUMONSCREEN))
Libindex++;
}
updatedisplay();
}
break;
case CH_UP:
if ( Editrow>0 )
editto(Editrow-1,Editcol);
else {
/* we're at the top, so try to scroll */
if ( Editcol==0 ) {
/* we're on the synth side */
if (Synindex>0)
Synindex--;
}
else {
/* we're on the lib side */
if (Libindex>0)
Libindex--;
}
updatedisplay();
}
break;
case CH_RIGHT:
if ( Editcol==0 )
editto(Editrow,1);
break;
case 'f':
filelist();
break;
default:
message("Unrecognized command! Press '?' for help.");
break;
}
}
}
filelist()
{
char *p, *q, buff[BUFSIZ];
int n, ninline = 0, nprinted = 0;
clearmess();
Currrow = -1; /* To start message on top line */
openls();
message("Files in current directory:");
strcpy(buff," ");
while ( (p=nextls()) != NULL ) {
/* add the next file to the line being constructed */
q = &buff[strlen(buff)];
strcpy(q,p);
q += (n=strlen(p));
while ( n++ < 15 )
*q++ = ' ';
*q = '\0';
if ( ninline++ > 3 ) {
message(buff);
if ( nprinted++ > 4 ) {
message("Press any key to continue ...");
getconsole();
clearmess();
nprinted = 0;
}
strcpy(buff," ");
ninline = 0;
}
}
if ( ninline > 0 )
message(buff);
closels();
}
libmouse()
{
int row, col;
getmouse(&row,&col);
if ( row <= FIRSTROW || row > FIRSTROW+NUMONSCREEN+1 )
goto getout;
if ( col < Cols/2 )
col = 0;
else
col = 1;
row = row - FIRSTROW - 1;
editto(row,col);
getout:
/* wait until mouse button is released */
while ( statmouse() > 0 )
;
}
do_goto()
{
int n, r, maxindex, new_ecol;
char sbuf[100], *sp;
message("");
message("Where to? ");
windgets(sbuf);
sp = sbuf;
switch(*sp++) {
case 's': /* synth side */
new_ecol = 0;
break;
case 'l': /* library side */
new_ecol = 1;
break;
default: /* no change in side */
new_ecol = Editcol;
sp--; /* but don't trash the first character */
break;
}
clearmess();
r = sscanf(sp, "%d", &n); /* this may fail - we handle it later */
if(Cvtnum != NULL) { /* convert to internal format if needed */
n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
}
if (Cvtanum != NULL) { /* convert using alphanumeric voice number */
n = (*Cvtanum)(sp) + 1;
}
if(r != 1) {
message("type one of: sn, ln, or n");
message(" s = synth side (literal character 's')");
message(" l = library side (literal character 'l')");
message(" n = voice number to select (an integer)");
return;
}
if(n <= 0 || n > Nvoices) { /* 1-based */
message("Bad voice number!");
return;
}
/* it can be done. nuke the old '*' and change columes (if needed) */
editchar(' ', Editrow, Editcol);
Editcol = new_ecol;
/* try to center it */
maxindex = Nvoices - NUMONSCREEN;
if(Editcol == 0) {
Synindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
if(Synindex < 0) { /* impossible to center */
Synindex = 0; /* so do your best */
} else if(Synindex > maxindex) {
Synindex = maxindex;
}
Editrow = (n - 1) - Synindex; /* and put a '*' on it */
} else {
Libindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
if(Libindex < 0) {
Libindex = 0;
} else if(Libindex > maxindex) {
Libindex = maxindex;
}
Editrow = (n - 1) - Libindex;
}
updatedisplay(); /* do the real work */
return;
}
upload(data)
char *data;
{
int c, n;
char num[16];
message("");
message("Upload TO synth:");
message(" c - current voice");
message(" a - ALL voices");
message("Choose --> ");
c = getconsole();
if ( c == 'c' ) {
clearmess();
if ( Sendone == NULL ) {
message("Single voices can't be sent to that synth!");
return;
}
message("What voice number to you want to send it TO? --> ");
windgets(num);
clearmess();
n = atoi(num);
if(Cvtnum != NULL) { /* convert to internal format if needed */
n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
}
if (Cvtanum != NULL) { /* howzabout alphanumeric format? */
n = (*Cvtanum)(num) + 1;
}
if ( n > 0 && n <= Nvoices ) {
if ( (*Sendone)(n-1,data) != 0 ) { /* 0-based on calls -SAF */
message("Unable to write data to synth!");
sprintf(Buff,"Reason: %s",Reason);
message(Buff);
}
} else {
message("Bad voice number!");
}
}
else if ( c == 'a' ) {
clearmess();
if ( Sendbulk != NULL )
(*Sendbulk)(Syndata);
else {
for ( n=0; n<Nvoices; n++ ) {
if ( (*Sendone)(n, &(VOICEBYTE(Syndata,n,0)) ) != 0 ) {
message("Unable to write data to synth!");
sprintf(Buff,"Reason: %s",Reason);
message(Buff);
break;
}
}
}
/* clearmess(); */
}
else {
clearmess();
message("Bad choice!");
}
}
helpmessage()
{
clearmess();
sprintf(Buff,"%s,%s,%s,%s - move around e - edit current voice",
STR_LEFT,STR_DOWN,STR_UP,STR_RIGHT);
message(Buff);
message("r - read voices from a file y - yank into buffer");
message("w - write voices to a file p - put from buffer");
message("b - cycle through library banks s - swap current voice with yank buffer");
message("t - transfer all voices f - list files in current directory");
message("d - download voices from synth c - set MIDI channel");
message("u - upload voices to synth g - 'goto' form of moving around");
message("q - quit <space> - play a note");
}
updatedisplay()
{
if ( Editcol==0 ) {
/* we're on the synth side */
syntodisplay(Synindex);
editto(Editrow,Editcol);
}
else {
/* we're on the lib side */
libtodisplay(Libindex);
editto(Editrow,Editcol);
}
}
pryankname()
{
char ybuff[33];
char *p;
windgoto(YANKROW,YANKCOL-4);
windstr(" ");
strcpy(ybuff,(*Nameof)(Yankdata));
/* take off trailing blanks */
p = ybuff + strlen(ybuff) - 1;
while ( p>ybuff && *p == ' ' )
*p-- = '\0';
windgoto(YANKROW,YANKCOL+7-strlen(ybuff)/2);
windstr(ybuff);
windrefresh();
}
transcmd()
{
int fromc;
message("");
message("Transfer ALL voices:");
message(" 1: <<----- from library bank to synth bank");
message(" 2: ----->> from synth bank to library bank");
message("1 or 2 --> ");
fromc = getconsole();
windputc(fromc);
if ( fromc!='1' && fromc!='2' ) {
clearmess();
return;
}
switch ( fromc ) {
case '1':
copyall(bankvoice(0),Syndata);
syntodisplay(Synindex);
clearmess();
message("Use the 'u'pload command to actually send the synth bank voices to the synth.");
break;
case '2':
copyall(Syndata,bankvoice(0));
libtodisplay(Libindex);
clearmess();
break;
}
}
copyall(fromdata,todata)
char *fromdata;
char *todata;
{
int n, v;
for ( v=0; v<Nvoices; v++ )
for ( n=0; n<Voicesize; n++ )
VOICEBYTE(todata,v,n) = VOICEBYTE(fromdata,v,n);
}
message(s)
char *s;
{
windgoto(++Currrow,0);
windstr(s);
windrefresh();
}
setchan()
{
int c;
message("New MIDI channel --> ");
windgets(Buff);
if ( (c=atoi(Buff)) <= 0 || c > 16 ) {
clearmess();
message("Invalid channel!");
}
else {
clearmess();
Channel = c;
showchan();
}
}
showchan()
{
windgoto(20,31);
windstr("MIDI Channel: ");
sprintf(Buff,"%d ",Channel);
windstr(Buff);
windrefresh();
}
/* read data from a file, filling the current library bank. */
readall()
{
char fname[100];
FILE *f;
int v, n, r;
message("File name --> ");
windgets(fname);
OPENBINFILE(f,fname,"r");
if (f == NULL ) {
sprintf(Buff,"Can't open '%s'!",fname);
message(Buff);
return;
}
/* Check the first byte. If it's 0xdd, then the format is mine. */
/* If the first byte is 0-31, it's also mine. */
n = (getc(f) & 0xff);
if ( n == 0xdd || n<=31 ) {
if ( n <= 31 )
ungetc(n,f);
/* This is my format, just raw data. */
for ( v=0; v<Nvoices; v++ ) {
char *p = bankvoice(v);
for ( n=0; n<Voicesize; n++ )
*p++ = getc(f);
}
r = 0;
}
/* code for other formats would go here */
else {
message("Unknown file format");
r = 1;
}
fclose(f);
if ( r==0 ) {
libtodisplay(Libindex=0);
clearmess();
}
}
/* write current library bank to a file */
writeall()
{
char fname[100];
FILE *f;
int v, n;
message("File name --> ");
windgets(fname);
OPENBINFILE(f,fname,"w");
if ( f == NULL ) {
sprintf(Buff,"Can't open '%s'!",fname);
message(Buff);
return;
}
putc(0xdd,f); /* magic byte to identify my format */
for ( v=0; v<Nvoices; v++ ) {
char *p = bankvoice(v);
for ( n=0; n<Voicesize; n++ )
putc(*p++,f);
}
fclose(f);
clearmess();
}
/* draw main library/synth voice bank screen */
drawall()
{
windclear();
template();
libtodisplay(Libindex);
syntodisplay(Synindex);
editto(Editrow,Editcol);
pryankname();
showchan();
}
/*
* tosyn
*
* Store the given 'data' in in voice 'voicenum' (both in Syndata
* AND on the synth itself). If swap is non-zero, the voice is swapped
* with the current voice in Syndata.
*/
tosyn(voicenum,data,swap)
char *data;
{
int n, t;
for ( n=0; n<Voicesize; n++ ) {
if ( swap ) {
t = VOICEBYTE(Syndata,voicenum,n);
VOICEBYTE(Syndata,voicenum,n) = data[n];
data[n] = t;
}
else
VOICEBYTE(Syndata,voicenum,n) = data[n];
}
}
tolib(voicenum,data,swap)
char *data;
{
int n, t;
char *p = bankvoice(voicenum);
for ( n=0; n<Voicesize; n++ ) {
if ( swap ) {
t = *p;
*p = data[n];
data[n] = t;
}
else
*p = data[n];
p++;
}
}
tocurrent(data,voicenum)
char *data;
int voicenum;
{
int n;
for ( n=0; n<Voicesize; n++ )
Currdata[n] = VOICEBYTE(data,voicenum,n);
(*Sendedit)(Currdata);
}
/*
* readsynth
*
* Read a bulk dump from the synth, with some tolerance for errors.
*/
readsynth(data)
char *data;
{
if ( Getbulk == NULL ) {
message("That synth is unable to dump anything!!");
return(1);
}
message("Trying to download data from synth...");
if ( (*Getbulk)(data) == 0 ) {
clearmess();
return(0);
}
message("Unable to read data from synth!");
sprintf(Buff,"Reason: %s",Reason);
message(Buff);
message("Perhaps connections are amiss?");
return(1);
}
char *
vnumtext(n)
{
static char vnbuff[6];
if ( Numof == NULL ) {
sprintf(vnbuff,"%2d",n);
return(vnbuff);
}
else
return((*Numof)(n - 1)); /* keep this 0-based */
}
/*
* syntodisplay(n)
*
* Tranfer Syndata names to dialog boxes (Dxvoices) starting at n.
*/
syntodisplay(n)
{
int k, r;
/* for the NUMONSCREEN dialog boxes */
for ( k=0; k<NUMONSCREEN; k++ ) {
r = FIRSTROW+1+k;
windgoto(r,LEFTSIDE);
sprintf(Buff,"%-3s",vnumtext(n+k+1));
windstr(Buff);
windgoto(r,LEFTSIDE+6);
windstr(" ");
/* pull the name out of the Syndata */
windgoto(r,LEFTSIDE+6);
windstr((*Nameof)( & (VOICEBYTE(Syndata,n+k,0) )) );
}
windrefresh();
}
/*
* libtodisplay
*
* Tranfer Libdata names to the screen, starting at voice 'firstv'.
*/
libtodisplay(firstv)
{
int k, r;
windgoto(FIRSTROW-1,RIGHTSIDE-1);
sprintf(Buff,"Library Voices (Bank %d)",Libbank+1);
windstr(Buff);
/* for the NUMONSCREEN dialog boxes */
for ( k=0; k<NUMONSCREEN; k++ ) {
r = FIRSTROW+1+k;
windgoto(r,RIGHTSIDE);
sprintf(Buff,"%-3s",vnumtext(firstv+k+1));
windstr(Buff);
windgoto(r,RIGHTSIDE+6);
windstr(" ");
/* pull the name out of the Libdata */
windgoto(r,RIGHTSIDE+6);
windstr((*Nameof)(bankvoice(firstv+k)));
}
windrefresh();
}
allnotesoff()
{
int n;
/* Go through all channels. */
for ( n=0; n<15; n++ ) {
sendmidi(n | 0xb0);
sendmidi(0x7b);
sendmidi(0x00);
}
}
/*
* Below are generic edit routines, which manage a screen display
* showing parameter values, and let you roam around and make changes.
* The display is managed by the contents of the P array, which
* contains the name, screen location, min/max values, etc. of
* each parameter.
*/
int Prow = 0;
int Pcol = 0;
int Parm = 0;
/* redraw the parameter screen */
showallparms(name)
char *name;
{
int n;
char *s;
windclear();
showname(name);
windgoto(1,0);
for(n=strlen(name)+6;n>0;n--)
windputc('=');
/* The L array contains arbitrary screen labels */
for ( n=0; L[n].l_text != NULL; n++ ) {
windgoto(L[n].l_row,L[n].l_col);
windstr(L[n].l_text);
}
/* Display each parameter value, and a label if there is one. */
for ( n=0; P[n].p_name != NULL; n++ ) {
if ( P[n].p_flags != 0 )
continue;
if ( (s=P[n].p_label) != NULL )
showstr(s,P[n].p_lrow,P[n].p_lcol,0);
showparam(n,0);
}
windrefresh();
}
showname(name)
char *name;
{
windgoto(0,0);
windstr("Name: ");
windgoto(0,6);
windstr(name);
}
showparam(n,eras)
{
char *p;
/* The p_tovis element of the P array is a function which, given */
/* the parameter value as an argument, returns a string which is */
/* what should be displayed on the screen. */
p = (*(P[n].p_tovis))(P[n].p_val);
showstr(p,P[n].p_vrow,P[n].p_vcol,eras);
}
showstr(p,row,col,eras)
register char *p;
register int col;
{
register int c;
windgoto(row,col);
while ( (c=(*p++)) != '\0' ) {
switch(c){
case '~':
switch( (c=(*p++)) ) {
case 'u': row--; goto wgoto;
case 'd': row++; goto wgoto;
case 'l': col--; goto wgoto;
case 'r': col++;
wgoto:
windgoto(row,col);
break;
default:
windputc(eras?' ':c);
col++;
break;
}
break;
default:
windputc(eras?' ':c);
col++;
break;
}
}
}
/* Allow roaming around and changing of parameter values. */
editdata(name,data)
char *name;
char *data; /* vmem format */
{
int c, n;
windclear();
windrefresh();
/* enable all the parameters */
for ( n=0; P[n].p_name != NULL; n++ )
enableparm(n);
/* Take the voice data and put it into P */
(*Datain)(data);
Prow = Pcol = 0;
Changed = 0;
Redraw = 1;
gotoparm(CH_RIGHT); /* Get to the first parameter */
for ( ;; ) {
if ( Redraw ) {
showallparms(name);
Redraw = 0;
}
windgoto(Prow,Pcol);
windrefresh();
c = mouseorkey();
if ( c == MOUSE ) {
editmouse();
continue;
}
switch(c){
case CH_RIGHT:
case CH_UP:
case CH_DOWN:
case CH_LEFT:
gotoparm(c);
break;
case CH_REDRAW:
showallparms(name);
break;
case 'N':
/* Allow changing of voice name */
windgoto(0,5);
windstr(" ");
windgoto(0,6);
windrefresh();
windgets(Buff);
if ( Buff[0]!='\0' && Buff[0]!='\n' )
(*Setnameof)(data,Buff);
showname(name=(*Nameof)(data));
Changed = 1;
break;
case CH_INC:
adjuparm(1);
break;
case CH_INC2:
adjuparm(4);
break;
case CH_INC3:
adjuparm(P[Parm].p_max - P[Parm].p_min);
break;
case CH_DEC:
adjuparm(-1);
break;
case CH_DEC2:
adjuparm(-4);
break;
case CH_DEC3:
adjuparm(P[Parm].p_min - P[Parm].p_max);
break;
#ifdef OLDSTUFF
case 'a':
sendaced(data);
playnote(0);
break;
#endif
case ' ':
case '\n':
#ifndef macintosh
case '\r':
#endif
if ( Changed ) {
(*Dataout)(data);
(*Sendedit)(data);
}
playnote(0);
break;
case '\033':
case '`':
allnotesoff();
break;
case 'q':
case EOF:
if ( Changed ) {
(*Dataout)(data);
(*Sendedit)(data);
}
return;
default:
break;
}
}
}
adjuparm(incdec)
{
int v, n;
v = P[Parm].p_val + incdec;
if ( v < (n=P[Parm].p_min) )
v = n;
if ( v > (n=P[Parm].p_max) )
v = n;
Changed = 1;
showparam(Parm,1); /* erase the old val */
P[Parm].p_val = v;
showparam(Parm,0); /* show the new val */
}
editmouse()
{
int row, col, thisparm;
getmouse(&row,&col);
thisparm = closeparm(row,col);
if ( thisparm == Parm ) {
if ( statmouse() > 1 )
adjuparm(-1); /* right button */
else if ( statmouse() == 1 ) /* added by mab - bug fix */
adjuparm(1); /* left button */
}
else {
Parm = thisparm;
Prow = P[Parm].p_vrow;
Pcol = P[Parm].p_vcol;
}
}
/* closeparm - Find the closest parameter */
closeparm(row,col)
{
register struct paraminfo *pp;
register int n;
int dist, mindist, minparm, dr, dc;
minparm = 0;
mindist = Rows + Cols;
for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
if ( pp->p_flags != 0 )
continue;
if ( (dr=row-(pp->p_vrow)) < 0 )
dr = -dr;
if ( (dc=col-(pp->p_vcol)) < 0 )
dc = -dc;
if ( (dist=dr*dr+dc*dc) < mindist ) {
minparm = n;
mindist = dist;
}
}
return(minparm);
}
/* playnote - play the 'auto' note */
playnote(i)
{
int pitch, vol, dur, chan;
long endtime;
pitch = getval("autopitch");
if(i == 0) { /* called from inside edit-mode */
chan = getval("autochan");
} else { /* called from the top level */
chan = Channel;
}
vol = getval("autovol");
dur = getval("autodur");
endtime = milliclock() + dur * 100;
midinote(1,chan,pitch,vol);
while ( milliclock() < endtime )
;
midinote(0,chan,pitch,vol);
}
/* gotoparm - search for the next parameter in the specified direction */
gotoparm(dir)
{
int n, k, inc, pm, orig, r = Prow, c = Pcol;
if ( dir==CH_LEFT || dir==CH_RIGHT ) {
if ( dir==CH_LEFT )
c--;
else
c++;
orig = c;
inc = 0;
pm = -1;
/* look up and down, alternately */
for ( n=2*Rows; n>0; n-- ) {
r += (pm * inc++);
pm = -pm;
if ( r < 0 || r >= Rows )
continue;
if ( dir == CH_LEFT ) {
for ( c=orig; c>=0; c-- ) {
if ( parmat(r,c) )
return;
}
}
else {
for ( c=orig; c<Cols; c++ ) {
if ( parmat(r,c) )
return;
}
}
}
return;
}
if ( dir==CH_DOWN || dir==CH_UP ) {
if ( dir==CH_DOWN )
r++;
else
r--;
orig = c;
while ( r >= 0 && r < Rows ) {
/* look toward both sides at the same time */
inc = 0;
pm = -1;
for ( k=2*Cols; k>0; k-- ) {
c += (pm * inc++);
pm = -pm;
if ( c < 0 || c >= Cols )
continue;
if ( parmat(r,c) )
return;
}
if ( dir==CH_DOWN )
r++;
else
r--;
c = orig;
}
return;
}
}
/* paramat - return non-zero if a parameter value is at position r,c */
parmat(r,c)
register int r, c;
{
register int n;
register struct paraminfo *pp;
for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
if ( pp->p_flags != 0 )
continue;
if ( pp->p_vrow==r && pp->p_vcol==c ) {
Prow = r;
Pcol = c;
Parm = n;
return(1);
}
}
return(0);
}
/* parmindex - return index (in P) of a given parameter name. */
parmindex(name)
char *name;
{
int n;
char *s;
for ( n=0; (s=P[n].p_name) != NULL; n++ ) {
if ( strcmp(s,name) == 0 )
return(n);
}
sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!",name);
windstr(Buff);
windrefresh();
return(-1);
}
setval(name,v)
char *name;
{
int n;
if ( (n=parmindex(name)) < 0 )
return;
P[n].p_val = v;
}
getval(name)
char *name;
{
int n;
if ( (n=parmindex(name)) < 0 )
return(0);
return(P[n].p_val);
}
enableparm(n)
{
if ( P[n].p_flags != 0 )
P[n].p_flags = 0;
}
disableparm(n)
{
if ( P[n].p_flags == 0 )
P[n].p_flags = 1;
}
midinote(onoff,chan,pitch,vol)
{
sendmidi( ((onoff==1)?(0x90):(0x80)) | ((chan-1)&0xf) );
sendmidi( pitch & 0x7f );
sendmidi( vol & 0x7f );
}
static char Nbuff[16];
char *visnum(v)
{
sprintf(Nbuff,"%d",v);
return(Nbuff);
}
char *visonoff(v)
{
if ( v==0 )
return("off");
else
return("on");
}
char *
bankvoice(voice)
{
int offset = Libbank * Nvoices * Voicesize + voice * Voicesize;
return(Libdata + offset);
}