#ifndef lint static char rcsid[] = "$Id: glib.c,v 1.6 89/05/06 17:13:24 lee Exp $"; #endif /* * GLIB - a Generic LIBrarian and editor for synths * * Tim Thompson's original with modifications by Michael Kesti, * Greg Lee, Alan Bland, Scott Snyder, Mark Rinfret * $Log: glib.c,v $ * Revision 1.6 89/05/06 17:13:24 lee * rel. to comp.sources.misc * */ #include "glib.h" #include 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; int Lastvalue = 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; int DataID = 0; /* Data Id for file write and read operations */ /* 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 Numonscreen = 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; #ifdef SSS int *scr_p; int NParams; #endif int synthinfileflag = 0; int synthoutfileflag = 0; char Syinfname[100], Syofname[100]; 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 */ int (*Filein)(); /* read file into file-storage format */ int (*Fileout)(); /* write file-storage format into file */ #ifdef SSS # define PARAMAT(r, c) (*(scr_p + Cols*(r) + (c))) #endif #define ERASEIT 1 #define DRAWIT 0 #define ONLEFT 1 #define ONRIGHT 0 main() { int n; hello(); windinit(); initstuff(); Numonscreen = Rows - 12; 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,23); #ifdef KAWAIK1 windstr("Kawai K1 Librarian/Editor"); #else #ifdef ROLANDD10 windstr("Roland D-10 Librarian/Editor"); #else windstr("GLIB - A Generic Librarian/Editor"); #endif #endif for ( n=1; n<=Nsynths; n++ ) libchoice(n); windgoto(8+Nsynths,27); windstr("q - Quit"); windgoto(11+Nsynths,27); windstr("Make selection --> "); windrefresh(); pick = mouseorkey(); if ( pick == 'q' || pick == EOF ) return(-1); if ( pick != MOUSE ) pick = pick - '0'; else { int row, col; getmousepos(&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); (void)sprintf(Buff,"%d - %s",n,E[n-1].ed_name); windstr(Buff); } #ifndef SINGLEDATA initstuff() { int n, banksize, maxvsize; maxvsize = 0; 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; np_name, p2->p_name); } init_params() { int i; if ( P == NULL ) return; for (NParams=0; P[NParams].p_name != NULL; NParams++) ; qsort((void *)P, NParams, sizeof(struct paraminfo), paramcmp); scr_p = (int *)alloc(Rows * Cols * sizeof(int)); clrdata((char *)scr_p, Rows * Cols * sizeof(int)); for (i=0; i= 0 && r < Rows && c >= 0 && c < Cols) PARAMAT(r, c) = i+1; } } #endif #ifndef SINGLEDATA 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; DataID = E[n].ed_dataid; Filein = E[n].ed_filein; Fileout = E[n].ed_fileout; 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; #ifdef SSS init_params(); #endif } unsetedit(n) { int k; DataID = 0; 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 "); windrefresh(); c = mouseorkey(); if ( c == MOUSE ) { libmouse(); continue; } if ( isprint(c) ) windputc(c); clearmess(); #ifdef THRUHACK if ( c == '\n' || c == '\r' ) { thrumode(); message("Play away..."); c = mouseorkey(); uartmode(); clearmess(); continue; } #endif 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 maxindex ) Synindex = maxindex; } else { /* we're on the lib side */ if ( (Libindex+=q/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(); editto(Editrow,Editcol); break; case 'D': /* download FROM file */ synthinfileflag = 1; case 'd': /* download FROM synth */ clrdata(Syndata,Nvoices*Voicesize); if ( readsynth(Syndata) == 0 ) { syntodisplay(Synindex=0); if(Editcol == 0) editto(Editrow,Editcol); } synthinfileflag = 0; break; case 'U': /* upload to file */ synthoutfileflag = 1; case 'u': /* upload TO synth */ if ( Editcol==0 ) { voicenum = Editrow+Synindex; data = &(VOICEBYTE(Syndata,voicenum,0)); } else data = bankvoice(Editrow+Libindex); upload(data); synthoutfileflag = 0; break; case 'r': readall(); if(Editcol == 1) editto(Editrow,Editcol); break; case 'R': readprintable(); if(Editcol == 1) editto(Editrow,Editcol); break; case 'w': writeall(); break; case 'W': writeprintable(); 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': if ( Datain == 0 ) { message("No editing support for that!"); break; } if ( Namesize == 0) p = NULL; else p = (*Nameof)(Currdata); if ( Editcol==0 ) { voicenum = Editrow+Synindex; data = &(VOICEBYTE(Syndata,voicenum,0)); editdata(p,data); windclear(); /* Update Currdata */ for ( n=0; n0 ) 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: case ALTCH_RIGHT: if ( Editcol==0 ) editto(Editrow,1); break; case 'f': filelist(); break; case 'm': mixem(); break; default: message("Unrecognized command! Press '?' for help."); break; } } } long Randx=1; int myrand() { return(((Randx = Randx * 1103515245L + 12345)>>16) & 0x7fff); } mixem() { int n, t, v; char *p1, *p2; Randx = milliclock(); for ( v=0; v 3 ) { message(buff); if ( nprinted++ > 4 ) { message("Press any key to continue ..."); (void)getconsole(); clearmess(); nprinted = 0; } strcpy(buff," "); ninline = 0; } } if ( ninline > 0 ) message(buff); closels(); } libmouse() { int row, col, q; getmousepos(&row,&col); if(Nvoices < Numonscreen) q = Nvoices; else q = Numonscreen; if ( row <= FIRSTROW || row > FIRSTROW+q+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,q; 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 (n) r = 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')"); #ifdef KAWAIK1 message(" n = voice number to select (letter + number)"); #else #ifdef KAWAIK5 message(" n = voice number to select (letter + number)"); #else message(" n = voice number to select (an integer)"); #endif #endif 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 */ if(Nvoices < Numonscreen) q = Nvoices; else q = Numonscreen; maxindex = Nvoices - q; if(Editcol == 0) { Synindex = (n - 1) - q/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) - q/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]; windarrow(ONLEFT,DRAWIT); message(""); if (synthoutfileflag) { message("Upload to synth file:"); message("Output synth file --> "); windgets(Syofname); flushmidi(); } if ( Sendone == NULL ) c = 'a'; /* no choice */ else { if (!synthoutfileflag) message("Upload TO synth:"); message(" c - current voice"); message(" a - ALL voices"); message("Choose --> "); c = getconsole(); } if ( c == 'c' ) { clearmess(); if ( Sendone == NULL ) { if (synthoutfileflag) (*Sendedit)(data); else message("Single voices can't be sent to that synth!"); goto getout; } 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!"); (void)sprintf(Buff,"Reason: %s",Reason); message(Buff); goto getout; } } else { message("Bad voice number!"); } } else if ( c == 'a' ) { clearmess(); if ( Sendbulk != NULL ) { message("Uploading to synth using bulk routine."); if ( (*Sendbulk)(Syndata) != 0 ) { message("Upload failure!"); (void)sprintf(Buff,"Reason: %s\n",Reason); message(Buff); goto getout; } } else { message("Uploading to synth using single routine."); for ( n=0; n"); } } helpmessage() { clearmess(); (void)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 - 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; if ( Namesize == 0 ) return; 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 "); windgets(Buff); if ( (c=atoi(Buff)) <= 0 || c > 16 ) { clearmess(); message("Invalid channel!"); } else { clearmess(); Channel = c; showchan(); } } showchan() { windgoto(Rows-3,31); windstr("MIDI Channel: "); (void)sprintf(Buff,"%d ",Channel); windstr(Buff); windrefresh(); } #ifdef DX7 #include #include long flength(handle) int handle; { struct stat buf; fstat(handle, &buf); return buf.st_size; } #endif /* read data from a file, filling the current library bank. */ readall() { char fname[100]; FILE *f; int v, n, r; char *p; windarrow(ONRIGHT,DRAWIT); message("File name --> "); windgets(fname); #ifdef BSD OPENBINFILE(f,fname,"r"); #else OPENBINFILE(f,fname,"rb"); #endif if (f == NULL ) { windarrow(ONRIGHT,ERASEIT); (void)sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } if ( Filein ) { r = (*Filein)(f,bankvoice(0)); if ( r ) message("Something went wrong reading that file!"); } else { /* If the first byte matches DataID, then the format is OK. */ if (DataID) n = (getc(f) & 0xff); else n = 0; #ifdef MWAVE v = getc(f); /* If there's a sysex header in the file, skip it */ if ( (v&0xff) == 0xf0 ) { int m; for ( m=0; m<6; m++ ) (void) getc(f); } else { (void)ungetc(v,f); } #endif #ifndef ROLANDD10 # ifndef KAWAIIK1 /* If we are running the Aztec C compiler, it's not yet ANSII. The abominable kludge that follows is therefore necessary. */ # ifdef AZTEC_C # ifdef DX7 # define SKIP_IT # endif # ifdef DX7S # define SKIP_IT # endif # ifndef SKIP_IT if (n != DataID && n <= 31) { (void)ungetc(n,f); n = DataID; } # endif # undef SKIP_IT # else # if !defined(DX7) && !defined(DX7S) if (n != DataID && n <= 31) { (void)ungetc(n,f); n = DataID; } # endif # endif # endif #endif #ifdef DX7S /* check for reading a DX7 file in DX7s mode */ if ( strcmp(Synthname, "DX7s") == 0 ) if (flength(fileno(f)) == 4096) { (void)ungetc(n, f); dx7Sread_dx7(f, bankvoice(0)); r = 0; goto done; } /* check for reading a DX7S file in DX7 mode */ if ( strcmp(Synthname, "DX7") == 0 ) { n = getc(f) & 0xff; if (n == 0xd7) { /* DX7s dataID */ dx7read_dx7S(f, bankvoice(0)); r = 0; goto done; } (void)ungetc(n, f); n = 0; } #endif #ifdef DX7 /* validate a DX7 file based on length */ if ( strcmp(Synthname, "DX7") == 0 ) { if (flength(fileno(f)) != Nvoices * Voicesize) n = DataID + 1; } #endif if ( n == DataID ) { p = bankvoice(0); for ( v=0; v "); windgets(fname); #ifdef BSD OPENBINFILE(pfin,fname,"r"); #else OPENBINFILE(pfin,fname,"rb"); #endif if (pfin == NULL ) { (void)sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } /* If the first byte matches DataID, then the format is OK. */ r = fscanf(pfin, "BANK TYPE %d", &n); v = -1; if ( r == 1 && n == DataID ) while (r) { r = fscanf(pfin, " %s ", vname); if (r == 1) { if (strcmp(vname, "voice") == 0) { if (v > 0) (*Dataout)(p); r = fscanf(pfin,"%d = %[ !-~]", &v, vname); if (r == 2 && v > 0) { p = bankvoice(v-1); (*Setnameof)(p, vname); } } else { r = fscanf(pfin, "= %d", &val); if (r == 1) setval(vname, val); } } if (r == EOF) r = 0; } else { (void)sprintf(Buff, "'%s' is invalid for this function!\n", fname); message(Buff); r = 1; } if (v > 0) (*Dataout)(p); (void)fclose(pfin); if ( r==0 ) { libtodisplay(Libindex=0); clearmess(); } } /* write current library bank to a file */ writeall() { char fname[100]; FILE *f; int v, n; char *p; windarrow(ONRIGHT,DRAWIT); sprintf(Buff,"Writing Library (Bank %d)",Libbank+1); message(Buff); message("File name --> "); windgets(fname); #ifdef BSD OPENBINFILE(f,fname,"w"); #else OPENBINFILE(f,fname,"wb"); #endif if ( f == NULL ) { windarrow(ONRIGHT,ERASEIT); (void)sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } p = bankvoice(0); if ( Fileout ) { (*Fileout)(f,p); } else { if (DataID) putc(DataID,f); /* write data identifier */ for ( v=0; v "); windgets(fname); #ifdef BSD OPENBINFILE(pfout,fname,"w"); #else OPENBINFILE(pfout,fname,"wb"); #endif if ( pfout == NULL ) { (void)sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } fprintf(pfout, "BANK TYPE %d\n", DataID); for (v=0; v ' ') { (*Datain)(p); fprintf(pfout, "voice %d = %s\n", v+1, q); pfoutflag = 1; (*Dataout)(p); pfoutflag = 0; } } (void)fclose(pfout); 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 "); windgets(Syinfname); synthoutfileflag = 1; flushmidi(); synthoutfileflag = 0; } else message("Downloading from synth"); Reason = NULL; r = (*Getbulk)(data); windarrow(ONLEFT,ERASEIT); if ( r == 0 ) { if ( Reason != NULL ) message(Reason); return(0); } message("Unable to read data from synth!"); (void)sprintf(Buff,"Reason: %s",Reason); message(Buff); message("Perhaps connections are amiss?"); return(1); } char * vnumtext(n) { static char vnbuff[6]; if ( Numof == NULL ) { (void)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, q; if(Nvoices < Numonscreen) q = Nvoices; else q = Numonscreen; for ( k=0; k0;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. */ #ifdef DX7 if (P[n].p_vrow < 0 || P[n].p_vcol < 0) return; p = (*(P[n].p_tovis))(P[n].p_val, eras); #else p = (*(P[n].p_tovis))(P[n].p_val); #endif showstr(p,P[n].p_vrow,P[n].p_vcol,eras); } #ifdef DX7 /* * define defaults for the graphics characters, if they haven't been specified * in machdep. */ # ifndef DRAW_VERT # define DRAW_VERT '|' # define DRAW_HORIZ '-' # define DRAW_CROSS '+' # define DRAW_UPTEE '+' # define DRAW_DOWNTEE '+' # define DRAW_LEFTTEE '+' # define DRAW_RIGHTTEE '+' # define DRAW_UPLEFT '+' # define DRAW_UPRIGHT '+' # define DRAW_DOWNLEFT '+' # define DRAW_DOWNRIGHT '+' # endif showstr(p,row,col,eras) register char *p; register int col; { register int c; int rept, mincol; mincol = col; windgoto(row,col); while ( (c=(*p++)) != '\0' ) { switch(c){ case '~': c = *p++; if (isdigit(c)) { rept = 0; while (isdigit(c)) { rept = 10*rept + (c-'0'); c = *p++; } } else rept = 1; while (rept--) { switch( c ) { case 'n': row++; col=mincol; goto wgoto; case 'u': row--; goto wgoto; case 'd': row++; goto wgoto; case 'l': col--; if (col < mincol) mincol = col; goto wgoto; case 'r': col++; wgoto: windgoto(row,col); break; case '|': c=DRAW_VERT; goto wput; case '-': c=DRAW_HORIZ; goto wput; case '+': c=DRAW_CROSS; goto wput; case 'T': c=DRAW_UPTEE; goto wput; case '^': c=DRAW_DOWNTEE; goto wput; case '<': c=DRAW_RIGHTTEE; goto wput; case '>': c=DRAW_LEFTTEE; goto wput; case '{': c=DRAW_UPLEFT; goto wput; case '}': c=DRAW_UPRIGHT; goto wput; case '[': c=DRAW_DOWNLEFT; goto wput; case ']': c=DRAW_DOWNRIGHT; wput: windputc(eras?' ':c); col++; break; default: windputc(eras?' ':c); col++; break; } } break; default: windputc(eras?' ':c); col++; break; } } } #else /* DX7 */ 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; } } } #endif /* 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; Lastvalue = 0; 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 ALTCH_RIGHT: case CH_UP: case ALTCH_UP: case CH_DOWN: case ALTCH_DOWN: case CH_LEFT: case ALTCH_LEFT: gotoparm(c); break; case CH_SAME: sameparm(); break; case CH_REDRAW: showallparms(name); break; case 'N': if ( Namesize != 0 ) { /* 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); Changed = 0; } 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; Lastvalue = v; Changed = 1; showparam(Parm,1); /* erase the old val */ P[Parm].p_val = v; showparam(Parm,0); /* show the new val */ } sameparm() { int v, n; v = Lastvalue; 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; getmousepos(&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; switch(dir) { case ALTCH_UP: dir = CH_UP; break; case ALTCH_DOWN: dir = CH_DOWN; break; case ALTCH_LEFT: dir = CH_LEFT; break; case ALTCH_RIGHT: dir = CH_RIGHT; break; } 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= 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; { #ifdef SSS int p = PARAMAT(r, c); if (p == 0 || P[p-1].p_flags) return 0; else { Parm = p-1; Prow = r; Pcol = c; return 1; } #else 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); #endif } /* parmindex - return index (in P) of a given parameter name. */ parmindex(name) char *name; { #ifdef SSS struct paraminfo key, *p; extern char *bsearch(); key.p_name = name; p = (struct paraminfo *)bsearch((void *)&key, (void *)P, NParams, sizeof(struct paraminfo), paramcmp); if (p == 0) { (void)sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!\n",name); windstr(Buff); windrefresh(); return(-1); } else return p-P; #else int n; char *s; for ( n=0; (s=P[n].p_name) != NULL; n++ ) { if ( strcmp(s,name) == 0 ) return(n); } (void)sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!\n",name); windstr(Buff); windrefresh(); return(-1); #endif } void setval(name,v) INT16 v; char *name; { int n; if ( (n=parmindex(name)) < 0 ) return; P[n].p_val = v; } int getval(name) char *name; { int n; if ( (n=parmindex(name)) < 0 ) return(0); if (pfoutflag) fprintf(pfout, "%s = %d\n", name, P[n].p_val); 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) { (void)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); }