home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 242.lha / GenericLIBrarian / source / glib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-07  |  43.1 KB  |  1,473 lines

  1. /*
  2.  * GLIB - a Generic LIBrarian and editor for synths
  3.  */
  4.  
  5. #include "glib.h"
  6. #include <ctype.h>
  7.  
  8. char *Reason = "";
  9.  
  10. int Currrow = 0;        /* at top of screen, for messages */
  11. int Libbank = 0;        /* from 0 to LIBBANKS-1, is the current library bank*/
  12. int Nsynths = 0;
  13.  
  14. char *Currdata;
  15. char *Yankdata;         /* current 'yank' buffer (middle of screen) */
  16.  
  17. struct peredinfo *PE;   /* array of per-editor miscellany */
  18.  
  19. char Buff[BUFSIZ];
  20. int Redraw = 0;         /* if non-0, edit screen is completely redrawn. */
  21.                         /* parameter functions can make use of this. */
  22. int Changed = 0;
  23.  
  24. /* All the global values below are set as appropriate for the */
  25. /* synthesizer currently being dealt with. */
  26.  
  27. int Nvoices = 0;
  28. int Voicesize =0;
  29. int Namesize = 0;
  30. int Libindex;           /* from 0 to Nvoices-1 */
  31. int Synindex;           /* from 0 to Nvoices-1 */
  32. int Channel;
  33. int Editrow;            /* from 0 to NUMONSCREEN-1 */
  34. int Editcol;            /* 0==synth, 1==library */
  35. char *Libdata;          /* current library data (includes all LIBBANKS) */
  36.                         /* ie. the stuff on the right side of the screen */
  37. char *Syndata;          /* current synth data (1 bank), ie. the left side */
  38. struct paraminfo *P;    /* list of parameter info */
  39. struct labelinfo *L;    /* arbitrary screen labels for edit screen */
  40. char *Synthname;
  41.  
  42. int (*Sendedit)();      /* function to send parameters to synth's edit buffer*/
  43. int (*Datain)();        /* convert data from file-storage format to the */
  44.                         /* format stored in the P[] parameter array (p_val) */
  45. int (*Dataout)();       /* reverse of Datain */
  46. int (*Sendone)();       /* function to send one (permanent) voice to synth */
  47. int (*Sendbulk)();      /* function to send bulk dump to synth */
  48. int (*Getbulk)();       /* reverse of Sendbulk */
  49. char *(*Nameof)();      /* pulls voice name out of file-storage data */
  50. int (*Setnameof)();     /* reverse of Nameof */
  51. char *(*Numof)();       /* convert voice number to on-screen text */
  52. int (*Cvtnum)();        /* convert visible voice number to std. format */
  53. int (*Cvtanum)();       /* convert alphanumeric voice number to std. format */
  54.                         /* should never define both Cvtnum and Cvtanum */
  55. main()
  56. {
  57.         int n;
  58.  
  59.         hello();
  60.         windinit();
  61.         initstuff();
  62.  
  63.         if ( Nsynths == 0 )
  64.                 windstr("Hey, the E array is empty?");
  65.         else if ( Nsynths == 1 ) {
  66.                 /* If there's only 1 synth, don't bother asking */
  67.                 setedit(0);
  68.                 libinteract();
  69.         }
  70.         else {
  71.                 while ( (n=choosesynth()) >= 0 ) {
  72.                         setedit(n);
  73.                         libinteract();
  74.                         unsetedit(n);
  75.                 }
  76.         }
  77.         bye();
  78. }
  79.  
  80. /* choose a synth, returning its position in the E array */
  81. choosesynth()
  82. {
  83.         int n, pick;
  84.  
  85.     retry:
  86.         flushconsole();
  87.         windclear();
  88.         windgoto(2,18);
  89.         windstr("GLIB - A Generic Librarian/Editor");
  90.  
  91.         for ( n=1; n<=Nsynths; n++ )
  92.                 libchoice(n);
  93.  
  94.         windgoto(10+n,16);
  95.         windstr("Choose your synth (or 'q' to quit) --> ");
  96.         windrefresh();
  97.         pick = mouseorkey();
  98.         if ( pick == 'q' || pick == EOF )
  99.                 return(-1);
  100.         if ( pick != MOUSE )
  101.                 pick = pick - '0';
  102.         else {
  103.                 int row, col;
  104.                 getmouse(&row,&col);
  105.                 /* wait until mouse goes down */
  106.                 while ( statmouse() > 0 )
  107.                         ;
  108.                 pick = row - 6; 
  109.         }
  110.         if ( pick < 1 || pick > Nsynths )
  111.                 goto retry;
  112.         return(pick-1);
  113. }
  114.  
  115. libchoice(n)
  116. {
  117.         windgoto(6+n,27);
  118.         sprintf(Buff,"%d  -  %s",n,E[n-1].ed_name);
  119.         windstr(Buff);
  120. }
  121.  
  122. initstuff()
  123. {
  124.         int n, banksize, maxvsize = 0;
  125.         char *p;
  126.         
  127.         for ( n=0; E[n].ed_name != NULL; n++ ) {
  128.                 if ( maxvsize < E[n].ed_vsize )
  129.                         maxvsize = E[n].ed_vsize;
  130.         }
  131.         Nsynths = n;
  132.         Currdata = alloc( maxvsize );
  133.  
  134.         /* allocate an array of peredinfo structs */
  135.         PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo)));
  136.         for ( n=0; n<Nsynths; n++ ) {
  137.                 banksize =  E[n].ed_nvoices * E[n].ed_vsize;
  138.                 p = PE[n].ed_libdata = alloc( LIBBANKS * banksize );
  139.                 clrdata(p,LIBBANKS*banksize);
  140.                 p = PE[n].ed_syndata = alloc( banksize );
  141.                 clrdata(p,banksize);
  142.                 p = PE[n].ed_yankdata = alloc( E[n].ed_vsize );
  143.                 clrdata(p,E[n].ed_vsize);
  144.                 PE[n].ed_libindex = 0;
  145.                 PE[n].ed_synindex = 0;
  146.                 PE[n].ed_channel = 1;
  147.                 PE[n].ed_erow = 0;
  148.                 PE[n].ed_ecol = 0;
  149.         }
  150. }
  151.  
  152. clrdata(data,size)
  153. char *data;
  154. {
  155.         register char *p = data, *endp = data+size;
  156.  
  157.         while ( p<endp )
  158.                 *p++ = 0;
  159. }
  160.  
  161. setedit(n)
  162. {
  163.         Synthname = E[n].ed_name;
  164.         Datain = E[n].ed_din;
  165.         Dataout = E[n].ed_dout;
  166.         Nvoices = E[n].ed_nvoices;
  167.         Sendedit = E[n].ed_sedit;
  168.         Sendone = E[n].ed_sone;
  169.         Sendbulk = E[n].ed_sbulk;
  170.         Getbulk = E[n].ed_gbulk;
  171.         Nameof = E[n].ed_nof;
  172.         Numof = E[n].ed_numof;
  173.         Cvtnum = E[n].ed_cvtnum;
  174.         Cvtanum = E[n].ed_cvtanum;
  175.         Setnameof = E[n].ed_snof;
  176.         Voicesize = E[n].ed_vsize;
  177.         Namesize = E[n].ed_nsize;
  178.         Libdata = PE[n].ed_libdata;
  179.         Syndata = PE[n].ed_syndata;
  180.         Yankdata = PE[n].ed_yankdata;
  181.         Libindex = PE[n].ed_libindex;
  182.         Synindex = PE[n].ed_synindex;
  183.         Channel = PE[n].ed_channel;
  184.         Editrow = PE[n].ed_erow;
  185.         Editcol = PE[n].ed_ecol;
  186.         clrdata(Currdata,Voicesize);
  187.         P = E[n].ed_params;
  188.         L = E[n].ed_labels;
  189. }
  190.  
  191. unsetedit(n)
  192. {
  193.         int k;
  194.  
  195.         PE[n].ed_libindex = Libindex;
  196.         PE[n].ed_synindex = Synindex;
  197.         PE[n].ed_channel = Channel;
  198.         PE[n].ed_erow = Editrow;
  199.         PE[n].ed_ecol = Editcol;
  200.         for ( k=0; k<Voicesize; k++ )
  201.                 PE[n].ed_yankdata[k] = Yankdata[k];
  202. }
  203.  
  204. /* template - show the boxes and such on the main library screen */
  205. template()
  206. {
  207.         int n, k, r;
  208.  
  209.         r = FIRSTROW-1;
  210.         sprintf(Buff,"%s Voices",Synthname);
  211.         n = 13 - strlen(Buff)/2;        /* center it */
  212.         windgoto(r,n<0?0:n);
  213.         windstr(Buff);
  214.         r++;
  215.         windgoto(r,0);
  216.         for ( n=0; n<26; n++ )
  217.                 windputc('=');
  218.         windgoto(r,52);
  219.         for ( n=0; n<26; n++ )
  220.                 windputc('=');
  221.         for ( n=r+1; n<(r+13); n++ ) {
  222.                 windgoto(n,0);
  223.                 windputc('|');
  224.                 windgoto(n,6);
  225.                 windputc('|');
  226.                 windgoto(n,25);
  227.                 windputc('|');
  228.  
  229.                 k=52;
  230.                 windgoto(n,k);
  231.                 windputc('|');
  232.                 windgoto(n,k+6);
  233.                 windputc('|');
  234.                 windgoto(n,k+25);
  235.                 windputc('|');
  236.         }
  237.         windgoto(r+13,0);
  238.         for ( n=0; n<26; n++ )
  239.                 windputc('=');
  240.         windgoto(r+13,52);
  241.         for ( n=0; n<26; n++ )
  242.                 windputc('=');
  243.  
  244.         windgoto(YANKROW-2,YANKCOL);
  245.         windstr("  Yank Buffer");
  246.         windgoto(YANKROW-1,YANKCOL);
  247.         windstr(" ------------- ");
  248.         windgoto(YANKROW,YANKCOL);
  249.         windstr("               ");
  250.         windgoto(YANKROW+1,YANKCOL);
  251.         windstr(" ------------- ");
  252.         windrefresh();
  253. }
  254.  
  255. /* clear the message area */
  256. clearmess()
  257. {
  258.         int n;
  259.         for(n=1;n<(FIRSTROW-1);n++)
  260.                 winderaserow(n);
  261.         Currrow = 0;
  262. }
  263.  
  264. /* set the current voice (ie. the synth's edit buffer) to the indicated */
  265. /* voice.  c==0 is the synth (left) side, c==1 is the library (right) side. */
  266. editto(r,c)
  267. {
  268.         int voicenum;
  269.  
  270.         /* Clear the existing '*' */
  271.         editchar(' ',Editrow,Editcol);
  272.         editchar('*',Editrow=r,Editcol=c);
  273.         if ( Editcol==0 ) {
  274.                 /* we're on the synth side */
  275.                 voicenum = Editrow+Synindex;
  276.                 tocurrent(Syndata,voicenum);
  277.         }
  278.         else {
  279.                 /* we're on the lib side */
  280.                 voicenum = Editrow+Libindex;
  281.                 tocurrent(bankvoice(0),voicenum);
  282.         }
  283. }
  284.  
  285. editchar(ec,r,c)
  286. {
  287.         r = r + FIRSTROW + 1;
  288.         if ( c == 0 )
  289.                 c = LEFTSIDE-1;
  290.         else
  291.                 c = RIGHTSIDE-1;
  292.         windgoto(r,c);
  293.         windputc(ec);
  294.         windrefresh();
  295. }
  296.  
  297. /* control interaction on the main library bank screen */
  298. libinteract()
  299. {
  300.         int c, n, swap, voicenum, maxindex;
  301.         char *p, *data;
  302.  
  303.         flushmidi();
  304.         drawall();
  305.         for ( ;; ) {
  306.                 Currrow = 0;
  307.                 winderaserow(Currrow);
  308.                 windgoto(Currrow,0);
  309.                 windstr("Command --> ");
  310.                 windrefresh();
  311.                 
  312.                 c = mouseorkey();
  313.                 if ( c == MOUSE ) {
  314.                         libmouse();
  315.                         continue;
  316.                 }
  317.  
  318.                 if ( isprint(c) )
  319.                         windputc(c);
  320.                 clearmess();
  321.                 switch ( c ) {
  322.                 case ' ':
  323.                         playnote(1);
  324.                         break;
  325.                 case '\n':
  326. #ifndef macintosh
  327.                 case '\r':
  328. #endif
  329.                         /* ignore */
  330.                         break;
  331.                 case EOF:
  332.                 case 'q':
  333.                         return;
  334.                 case CH_REDRAW:
  335.                         drawall();
  336.                         break;
  337.                 case 's':
  338.                 case 'p':
  339.                         swap = (c=='s')?1:0;
  340.                         if ( Editcol==0 )
  341.                                 tosyn(Synindex+Editrow,Yankdata,swap);
  342.                         else
  343.                                 tolib(Libindex+Editrow,Yankdata,swap);
  344.                         updatedisplay();
  345.                         pryankname();
  346.                         break;
  347.                 case 'y':
  348.                         for(n=0;n<Voicesize;n++)
  349.                                 Yankdata[n] = Currdata[n];
  350.                         pryankname();
  351.                         break;
  352.                 case '?':
  353.                         helpmessage();
  354.                         break;
  355.                 case SCR_DOWN:
  356.                         maxindex = Nvoices - NUMONSCREEN;
  357.                         if ( Editcol==0 ) {
  358.                                 /* we're on the synth side */
  359.                                 if ( (Synindex+=NUMONSCREEN/2) > maxindex )
  360.                                         Synindex = maxindex;
  361.                         }
  362.                         else {
  363.                                 /* we're on the lib side */
  364.                                 if ( (Libindex+=NUMONSCREEN/2) > maxindex )
  365.                                         Libindex = maxindex;
  366.                         }
  367.                         updatedisplay();
  368.                         break;
  369.                 case SCR_UP:
  370.                         if ( Editcol==0 ) {
  371.                                 /* we're on the synth side */
  372.                                 if ( (Synindex-=NUMONSCREEN/2) < 0 )
  373.                                         Synindex = 0;
  374.                         }
  375.                         else {
  376.                                 /* we're on the lib side */
  377.                                 if ( (Libindex-=NUMONSCREEN/2) < 0 )
  378.                                         Libindex = 0;
  379.                         }
  380.                         updatedisplay();
  381.                         break;
  382.                 case '\033':
  383.                 case '`':
  384.                         allnotesoff();
  385.                         break;
  386.                 case 't':
  387.                         transcmd();
  388.                         break;
  389.                 case 'd':       /* download from synth to display */
  390.                         clrdata(Syndata,Nvoices*Voicesize);
  391.                         if ( readsynth(Syndata) == 0 )
  392.                                 syntodisplay(Synindex=0);
  393.                         break;
  394.                 case 'u':       /* upload TO synth */
  395.                         if ( Editcol==0 ) {
  396.                                 voicenum = Editrow+Synindex;
  397.                                 data = &(VOICEBYTE(Syndata,voicenum,0));
  398.                         }
  399.                         else
  400.                                 data = bankvoice(Editrow+Libindex);
  401.                         upload(data);
  402.                         break;
  403.                 case 'r':
  404.                         readall();
  405.                         break;
  406.                 case 'w':
  407.                         writeall();
  408.                         break;
  409.                 case 'c':
  410.                         setchan();
  411.                         break;
  412.                 case 'b':
  413.                         /* cycle through banks, from 0 to LIBBANKS-1 */
  414.                         if ( ++Libbank >= LIBBANKS )
  415.                                 Libbank = 0;
  416.                         libtodisplay(Libindex);
  417.                         updatedisplay();
  418.                         break;
  419.                 case 'e':
  420.                         p = (*Nameof)(Currdata);
  421.                         if ( Editcol==0 ) {
  422.                                 voicenum = Editrow+Synindex;
  423.                                 data = &(VOICEBYTE(Syndata,voicenum,0));
  424.                                 editdata(p,data);
  425.                                 windclear();
  426.                                 /* Update Currdata */
  427.                                 for ( n=0; n<Voicesize; n++ )
  428.                                     Currdata[n] = VOICEBYTE(Syndata,voicenum,n);
  429.                         }
  430.                         else {
  431.                                 data = bankvoice(Editrow+Libindex);
  432.                                 editdata(p,data);
  433.                         }
  434.                         drawall();
  435.                         break;
  436.                 case 'g': /* goto a specific voice */
  437.                         do_goto();
  438.                         break;
  439.                 case CH_LEFT:
  440.                         if ( Editcol==1 )
  441.                                 editto(Editrow,0);
  442.                         break;
  443.                 case CH_DOWN:
  444.                         if ( Editrow < (NUMONSCREEN-1) )
  445.                                 editto(Editrow+1,Editcol);
  446.                         else {
  447.                                 /* we're at the bottom, so try to scroll */
  448.                                 if ( Editcol==0 ) {
  449.                                         /* we're on the synth side */
  450.                                         if (Synindex<(Nvoices-NUMONSCREEN))
  451.                                                 Synindex++;
  452.                                 }
  453.                                 else {
  454.                                         /* we're on the lib side */
  455.                                         if (Libindex<(Nvoices-NUMONSCREEN))
  456.                                                 Libindex++;
  457.                                 }
  458.                                 updatedisplay();
  459.                         }
  460.                         break;
  461.                 case CH_UP:
  462.                         if ( Editrow>0 )
  463.                                 editto(Editrow-1,Editcol);
  464.                         else {
  465.                                 /* we're at the top, so try to scroll */
  466.                                 if ( Editcol==0 ) {
  467.                                         /* we're on the synth side */
  468.                                         if (Synindex>0)
  469.                                                 Synindex--;
  470.                                 }
  471.                                 else {
  472.                                         /* we're on the lib side */
  473.                                         if (Libindex>0)
  474.                                                 Libindex--;
  475.                                 }
  476.                                 updatedisplay();
  477.                         }       
  478.                         break;
  479.                 case CH_RIGHT:
  480.                         if ( Editcol==0 )
  481.                                 editto(Editrow,1);
  482.                         break;
  483.                 case 'f':
  484.                         filelist();
  485.                         break;
  486.                 default:
  487.                         message("Unrecognized command!  Press '?' for help.");
  488.                         break;
  489.                 }
  490.         }
  491. }
  492.  
  493. filelist()
  494. {
  495.         char *p, *q, buff[BUFSIZ];
  496.         int n, ninline = 0, nprinted = 0;
  497.  
  498.         clearmess();
  499.         Currrow = -1;   /* To start message on top line */
  500.         openls();
  501.         message("Files in current directory:");
  502.         strcpy(buff,"  ");
  503.         while ( (p=nextls()) != NULL ) {
  504.                 /* add the next file to the line being constructed */
  505.                 q = &buff[strlen(buff)];
  506.                 strcpy(q,p);
  507.                 q += (n=strlen(p));
  508.                 while ( n++ < 15 )
  509.                         *q++ = ' ';
  510.                 *q = '\0';
  511.                 if ( ninline++ > 3 ) {
  512.                         message(buff);
  513.                         if ( nprinted++ > 4 ) {
  514.                                 message("Press any key to continue ...");
  515.                                 getconsole();
  516.                                 clearmess();
  517.                                 nprinted = 0;
  518.                         }
  519.                         strcpy(buff,"  ");
  520.                         ninline = 0;
  521.                 }
  522.         }
  523.         if ( ninline > 0 )
  524.                 message(buff);
  525.         closels();
  526. }
  527.  
  528. libmouse()
  529. {
  530.         int row, col;
  531.  
  532.         getmouse(&row,&col);
  533.         if ( row <= FIRSTROW || row > FIRSTROW+NUMONSCREEN+1 )
  534.                 goto getout;
  535.         if ( col < Cols/2 )
  536.                 col = 0;
  537.         else
  538.                 col = 1;
  539.         row = row - FIRSTROW - 1;
  540.         editto(row,col);
  541. getout:
  542.         /* wait until mouse button is released */
  543.         while ( statmouse() > 0 )
  544.                 ;
  545. }
  546.  
  547. do_goto()
  548. {
  549.         int n, r, maxindex, new_ecol;
  550.         char sbuf[100], *sp;
  551.         
  552.         message("");
  553.         message("Where to? ");
  554.         windgets(sbuf);
  555.         
  556.         sp = sbuf;
  557.         switch(*sp++) {
  558.           case 's': /* synth side */
  559.                 new_ecol = 0;
  560.                 break;
  561.           case 'l': /* library side */
  562.                 new_ecol = 1;
  563.                 break;
  564.           default: /* no change in side */
  565.                 new_ecol = Editcol;
  566.                 sp--;   /* but don't trash the first character */
  567.                 break;
  568.         }
  569.         
  570.         clearmess();
  571.         r = sscanf(sp, "%d", &n); /* this may fail - we handle it later */
  572.         if(Cvtnum != NULL) { /* convert to internal format if needed */
  573.                 n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  574.         }
  575.         if (Cvtanum != NULL) { /* convert using alphanumeric voice number */
  576.                 n = (*Cvtanum)(sp) + 1;
  577.         }
  578.         if(r != 1) {
  579.                 message("type one of: sn, ln, or n");
  580.                 message("  s = synth side (literal character 's')");
  581.                 message("  l = library side (literal character 'l')");
  582.                 message("  n = voice number to select (an integer)");
  583.                 return;
  584.         }
  585.         if(n <= 0 || n > Nvoices) { /* 1-based */
  586.                 message("Bad voice number!");
  587.                 return;
  588.         }
  589.         
  590.         /* it can be done.  nuke the old '*' and change columes (if needed) */
  591.         editchar(' ', Editrow, Editcol);
  592.         Editcol = new_ecol;
  593.         
  594.         /* try to center it */
  595.         maxindex = Nvoices - NUMONSCREEN;
  596.         if(Editcol == 0) {
  597.                 Synindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
  598.                 if(Synindex < 0) { /* impossible to center */
  599.                         Synindex = 0; /* so do your best */
  600.                 } else if(Synindex > maxindex) {
  601.                         Synindex = maxindex;
  602.                 }
  603.                 Editrow = (n - 1) - Synindex; /* and put a '*' on it */
  604.         } else {
  605.                 Libindex = (n - 1) - NUMONSCREEN/2; /* 0-based */
  606.                 if(Libindex < 0) {
  607.                         Libindex = 0;
  608.                 } else if(Libindex > maxindex) {
  609.                         Libindex = maxindex;
  610.                 }
  611.                 Editrow = (n - 1) - Libindex;
  612.         }
  613.         
  614.         updatedisplay(); /* do the real work */
  615.         return;
  616. }
  617.  
  618. upload(data)
  619. char *data;
  620. {
  621.         int c, n;
  622.         char num[16];
  623.  
  624.         message("");
  625.         message("Upload TO synth:");
  626.         message("                 c - current voice");
  627.         message("                 a - ALL voices");
  628.         message("Choose --> ");
  629.         c = getconsole();
  630.         if ( c == 'c' ) {
  631.                 clearmess();
  632.                 if ( Sendone == NULL ) {
  633.                         message("Single voices can't be sent to that synth!");
  634.                         return;
  635.                 }
  636.                 message("What voice number to you want to send it TO? --> ");
  637.                 windgets(num);
  638.                 clearmess();
  639.                 n = atoi(num);
  640.                 if(Cvtnum != NULL) { /* convert to internal format if needed */
  641.                         n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */
  642.                 }
  643.                 if (Cvtanum != NULL) { /* howzabout alphanumeric format? */
  644.                         n = (*Cvtanum)(num) + 1;
  645.                 }
  646.                 if ( n > 0 && n <= Nvoices ) {
  647.                         if ( (*Sendone)(n-1,data) != 0 ) { /* 0-based on calls -SAF */
  648.                                 message("Unable to write data to synth!");
  649.                                 sprintf(Buff,"Reason: %s",Reason);
  650.                                 message(Buff);
  651.                         }
  652.                 } else {
  653.                         message("Bad voice number!");
  654.                 }
  655.         }
  656.         else if ( c == 'a' ) {
  657.                 clearmess();
  658.                 if ( Sendbulk != NULL )
  659.                         (*Sendbulk)(Syndata);
  660.                 else {
  661.                         for ( n=0; n<Nvoices; n++ ) {
  662.                                 if ( (*Sendone)(n, &(VOICEBYTE(Syndata,n,0)) ) != 0 ) {
  663.                                         message("Unable to write data to synth!");
  664.                                         sprintf(Buff,"Reason: %s",Reason);
  665.                                         message(Buff);
  666.                                         break;
  667.                                 }
  668.                         }
  669.                 }
  670.                 /* clearmess(); */
  671.         }
  672.         else {
  673.                 clearmess();
  674.                 message("Bad choice!");
  675.         }
  676. }
  677.  
  678. helpmessage()
  679. {
  680. clearmess();
  681. sprintf(Buff,"%s,%s,%s,%s - move around              e - edit current voice",
  682.         STR_LEFT,STR_DOWN,STR_UP,STR_RIGHT);
  683. message(Buff);
  684. message("r - read voices from a file        y - yank into buffer");
  685. message("w - write voices to a file         p - put from buffer");
  686. message("b - cycle through library banks    s - swap current voice with yank buffer");
  687. message("t - transfer all voices            f - list files in current directory");
  688. message("d - download voices from synth     c - set MIDI channel");
  689. message("u - upload voices to synth         g - 'goto' form of moving around");
  690. message("q - quit                           <space> - play a note");
  691. }
  692.  
  693. updatedisplay()
  694. {
  695.         if ( Editcol==0 ) {
  696.                 /* we're on the synth side */
  697.                 syntodisplay(Synindex);
  698.                 editto(Editrow,Editcol);
  699.         }
  700.         else {
  701.                 /* we're on the lib side */
  702.                 libtodisplay(Libindex);
  703.                 editto(Editrow,Editcol);
  704.         }
  705. }
  706.  
  707. pryankname()
  708. {
  709.         char ybuff[33];
  710.         char *p;
  711.  
  712.         windgoto(YANKROW,YANKCOL-4);
  713.         windstr("                    ");
  714.         strcpy(ybuff,(*Nameof)(Yankdata));
  715.         /* take off trailing blanks */
  716.         p = ybuff + strlen(ybuff) - 1;
  717.         while ( p>ybuff && *p == ' ' )
  718.                 *p-- = '\0';
  719.         windgoto(YANKROW,YANKCOL+7-strlen(ybuff)/2);
  720.         windstr(ybuff);
  721.         windrefresh();
  722. }
  723.  
  724. transcmd()
  725. {
  726.         int fromc;
  727.  
  728.         message("");
  729.         message("Transfer ALL voices:");
  730.         message("                       1:   <<-----   from library bank to synth bank");
  731.         message("                       2:   ----->>   from synth bank to library bank");
  732.         message("1 or 2 --> ");
  733.         fromc = getconsole();
  734.         windputc(fromc);
  735.         if ( fromc!='1' && fromc!='2' ) {
  736.                 clearmess();
  737.                 return;
  738.         }
  739.         switch ( fromc ) {
  740.         case '1':
  741.                 copyall(bankvoice(0),Syndata);
  742.                 syntodisplay(Synindex);
  743.                 clearmess();
  744.                 message("Use the 'u'pload command to actually send the synth bank voices to the synth.");
  745.                 break;
  746.         case '2':
  747.                 copyall(Syndata,bankvoice(0));
  748.                 libtodisplay(Libindex);
  749.                 clearmess();
  750.                 break;
  751.         }
  752. }
  753.  
  754. copyall(fromdata,todata)
  755. char *fromdata;
  756. char *todata;
  757. {
  758.         int n, v;
  759.  
  760.         for ( v=0; v<Nvoices; v++ )
  761.                 for ( n=0; n<Voicesize; n++ )
  762.                         VOICEBYTE(todata,v,n) = VOICEBYTE(fromdata,v,n);
  763. }
  764.  
  765. message(s)
  766. char *s;
  767. {
  768.         windgoto(++Currrow,0);
  769.         windstr(s);
  770.         windrefresh();
  771. }
  772.  
  773. setchan()
  774. {
  775.         int c;
  776.  
  777.         message("New MIDI channel --> ");
  778.         windgets(Buff);
  779.         if ( (c=atoi(Buff)) <= 0 || c > 16 ) {
  780.                 clearmess();
  781.                 message("Invalid channel!");
  782.         }
  783.         else {
  784.                 clearmess();
  785.                 Channel = c;
  786.                 showchan();
  787.         }
  788. }
  789.  
  790. showchan()
  791. {
  792.         windgoto(20,31);
  793.         windstr("MIDI Channel: ");
  794.         sprintf(Buff,"%d ",Channel);
  795.         windstr(Buff);
  796.         windrefresh();
  797. }
  798.  
  799. /* read data from a file, filling the current library bank. */
  800. readall()
  801. {
  802.         char fname[100];
  803.         FILE *f;
  804.         int v, n, r;
  805.  
  806.         message("File name --> ");
  807.         windgets(fname);
  808.         OPENBINFILE(f,fname,"r");
  809.         if (f == NULL ) {
  810.                 sprintf(Buff,"Can't open '%s'!",fname);
  811.                 message(Buff);
  812.                 return;
  813.         }
  814.         /* Check the first byte.  If it's 0xdd, then the format is mine. */
  815.         /* If the first byte is 0-31, it's also mine. */
  816.         n = (getc(f) & 0xff);
  817.         if ( n == 0xdd || n<=31 ) {
  818.                 if ( n <= 31 )
  819.                         ungetc(n,f);
  820.                 /* This is my format, just raw data. */
  821.                 for ( v=0; v<Nvoices; v++ ) {
  822.                         char *p = bankvoice(v);
  823.                         for ( n=0; n<Voicesize; n++ )
  824.                                 *p++ = getc(f);
  825.                 }
  826.                 r = 0;
  827.         }
  828.         /* code for other formats would go here */
  829.         else {
  830.                 message("Unknown file format");
  831.                 r = 1;
  832.         }
  833.         fclose(f);
  834.         if ( r==0 ) {
  835.                 libtodisplay(Libindex=0);
  836.                 clearmess();
  837.         }
  838. }
  839.  
  840. /* write current library bank to a file */
  841. writeall()
  842. {
  843.         char fname[100];
  844.         FILE *f;
  845.         int v, n;
  846.  
  847.         message("File name --> ");
  848.         windgets(fname);
  849.         OPENBINFILE(f,fname,"w");
  850.         if ( f == NULL ) {
  851.                 sprintf(Buff,"Can't open '%s'!",fname);
  852.                 message(Buff);
  853.                 return;
  854.         }
  855.         putc(0xdd,f);   /* magic byte to identify my format */
  856.         for ( v=0; v<Nvoices; v++ ) {
  857.                 char *p = bankvoice(v);
  858.                 for ( n=0; n<Voicesize; n++ )
  859.                         putc(*p++,f);
  860.         }
  861.         fclose(f);
  862.         clearmess();
  863. }
  864.  
  865. /* draw main library/synth voice bank screen */
  866. drawall()
  867. {
  868.         windclear();
  869.         template();
  870.         libtodisplay(Libindex);
  871.         syntodisplay(Synindex);
  872.         editto(Editrow,Editcol);
  873.         pryankname();
  874.         showchan();
  875. }
  876.  
  877. /*
  878.  * tosyn
  879.  *
  880.  * Store the given 'data' in in voice 'voicenum' (both in Syndata
  881.  * AND on the synth itself).  If swap is non-zero, the voice is swapped
  882.  * with the current voice in Syndata.
  883.  */
  884.  
  885. tosyn(voicenum,data,swap)
  886. char *data;
  887. {
  888.         int n, t;
  889.  
  890.         for ( n=0; n<Voicesize; n++ ) {
  891.                 if ( swap ) {
  892.                         t = VOICEBYTE(Syndata,voicenum,n);
  893.                         VOICEBYTE(Syndata,voicenum,n) = data[n];
  894.                         data[n] = t;
  895.                 }
  896.                 else
  897.                         VOICEBYTE(Syndata,voicenum,n) = data[n];
  898.         }
  899. }
  900.  
  901. tolib(voicenum,data,swap)
  902. char *data;
  903. {
  904.         int n, t;
  905.         char *p = bankvoice(voicenum);
  906.  
  907.         for ( n=0; n<Voicesize; n++ ) {
  908.                 if ( swap ) {
  909.                         t = *p;
  910.                         *p = data[n];
  911.                         data[n] = t;
  912.                 }
  913.                 else
  914.                         *p = data[n];
  915.                 p++;
  916.         }
  917. }
  918.  
  919. tocurrent(data,voicenum)
  920. char *data;
  921. int voicenum;
  922. {
  923.         int n;
  924.  
  925.         for ( n=0; n<Voicesize; n++ )
  926.                 Currdata[n] = VOICEBYTE(data,voicenum,n);
  927.         (*Sendedit)(Currdata);
  928. }
  929.  
  930. /*
  931.  * readsynth
  932.  *
  933.  * Read a bulk dump from the synth, with some tolerance for errors.
  934.  */
  935. readsynth(data)
  936. char *data;
  937. {
  938.         if ( Getbulk == NULL ) {
  939.                 message("That synth is unable to dump anything!!");
  940.                 return(1);
  941.         }
  942.         message("Trying to download data from synth...");
  943.         if ( (*Getbulk)(data) == 0 ) {
  944.                 clearmess();
  945.                 return(0);
  946.         }
  947.         message("Unable to read data from synth!");
  948.         sprintf(Buff,"Reason: %s",Reason);
  949.         message(Buff);
  950.         message("Perhaps connections are amiss?");
  951.         return(1);
  952. }
  953.  
  954. char *
  955. vnumtext(n)
  956. {
  957.         static char vnbuff[6];
  958.  
  959.         if ( Numof == NULL ) {
  960.                 sprintf(vnbuff,"%2d",n);
  961.                 return(vnbuff);
  962.         }
  963.         else
  964.                 return((*Numof)(n - 1)); /* keep this 0-based */
  965. }
  966.  
  967. /*
  968.  * syntodisplay(n)
  969.  *
  970.  * Tranfer Syndata names to dialog boxes (Dxvoices) starting at n.
  971.  */
  972. syntodisplay(n)
  973. {
  974.         int k, r;
  975.  
  976.         /* for the NUMONSCREEN dialog boxes */
  977.         for ( k=0; k<NUMONSCREEN; k++ ) {
  978.                 r = FIRSTROW+1+k;
  979.                 windgoto(r,LEFTSIDE);
  980.                 sprintf(Buff,"%-3s",vnumtext(n+k+1));
  981.                 windstr(Buff);
  982.                 windgoto(r,LEFTSIDE+6);
  983.                 windstr("                 ");
  984.  
  985.                 /* pull the name out of the Syndata */
  986.                 windgoto(r,LEFTSIDE+6);
  987.                 windstr((*Nameof)( & (VOICEBYTE(Syndata,n+k,0) )) );
  988.         }
  989.         windrefresh();
  990. }
  991.  
  992. /*
  993.  * libtodisplay
  994.  *
  995.  * Tranfer Libdata names to the screen, starting at voice 'firstv'.
  996.  */
  997.  
  998. libtodisplay(firstv)
  999. {
  1000.         int k, r;
  1001.  
  1002.         windgoto(FIRSTROW-1,RIGHTSIDE-1);
  1003.         sprintf(Buff,"Library Voices (Bank %d)",Libbank+1);
  1004.         windstr(Buff);
  1005.  
  1006.         /* for the NUMONSCREEN dialog boxes */
  1007.         for ( k=0; k<NUMONSCREEN; k++ ) {
  1008.                 r = FIRSTROW+1+k;
  1009.                 windgoto(r,RIGHTSIDE);
  1010.                 sprintf(Buff,"%-3s",vnumtext(firstv+k+1));
  1011.                 windstr(Buff);
  1012.                 windgoto(r,RIGHTSIDE+6);
  1013.                 windstr("                 ");
  1014.  
  1015.                 /* pull the name out of the Libdata */
  1016.                 windgoto(r,RIGHTSIDE+6);
  1017.                 windstr((*Nameof)(bankvoice(firstv+k)));
  1018.         }
  1019.         windrefresh();
  1020. }
  1021.  
  1022. allnotesoff()
  1023. {
  1024.         int n;
  1025.  
  1026.         /* Go through all channels. */
  1027.         for ( n=0; n<15; n++ ) {
  1028.                 sendmidi(n | 0xb0);
  1029.                 sendmidi(0x7b);
  1030.                 sendmidi(0x00);
  1031.         }
  1032. }
  1033.  
  1034. /*
  1035.  * Below are generic edit routines, which manage a screen display
  1036.  * showing parameter values, and let you roam around and make changes.
  1037.  * The display is managed by the contents of the P array, which
  1038.  * contains the name, screen location, min/max values, etc. of
  1039.  * each parameter.
  1040.  */
  1041.  
  1042. int Prow = 0;
  1043. int Pcol = 0;
  1044. int Parm = 0;
  1045.  
  1046. /* redraw the parameter screen */
  1047. showallparms(name)
  1048. char *name;
  1049. {
  1050.         int n;
  1051.         char *s;
  1052.  
  1053.         windclear();
  1054.  
  1055.         showname(name);
  1056.         windgoto(1,0);
  1057.         for(n=strlen(name)+6;n>0;n--)
  1058.                 windputc('=');
  1059.  
  1060.         /* The L array contains arbitrary screen labels */
  1061.         for ( n=0; L[n].l_text != NULL; n++ ) {
  1062.                 windgoto(L[n].l_row,L[n].l_col);
  1063.                 windstr(L[n].l_text);
  1064.         }
  1065.         /* Display each parameter value, and a label if there is one. */
  1066.         for ( n=0; P[n].p_name != NULL; n++ ) {
  1067.                 if ( P[n].p_flags != 0 )
  1068.                         continue;
  1069.                 if ( (s=P[n].p_label) != NULL )
  1070.                         showstr(s,P[n].p_lrow,P[n].p_lcol,0);
  1071.                 showparam(n,0);
  1072.         }
  1073.         windrefresh();
  1074. }
  1075.  
  1076. showname(name)
  1077. char *name;
  1078. {
  1079.         windgoto(0,0);
  1080.         windstr("Name:                 ");
  1081.         windgoto(0,6);
  1082.         windstr(name);
  1083. }
  1084.  
  1085. showparam(n,eras)
  1086. {
  1087.         char *p;
  1088.  
  1089.         /* The p_tovis element of the P array is a function which, given */
  1090.         /* the parameter value as an argument, returns a string which is */
  1091.         /* what should be displayed on the screen. */
  1092.         p = (*(P[n].p_tovis))(P[n].p_val);
  1093.         showstr(p,P[n].p_vrow,P[n].p_vcol,eras);
  1094. }
  1095.  
  1096. showstr(p,row,col,eras)
  1097. register char *p;
  1098. register int col;
  1099. {
  1100.         register int c;
  1101.  
  1102.         windgoto(row,col);
  1103.         while ( (c=(*p++)) != '\0' ) {
  1104.                 switch(c){
  1105.                 case '~':
  1106.                         switch( (c=(*p++)) ) {
  1107.                         case 'u': row--; goto wgoto;
  1108.                         case 'd': row++; goto wgoto;
  1109.                         case 'l': col--; goto wgoto;
  1110.                         case 'r': col++;
  1111.                             wgoto:
  1112.                                 windgoto(row,col);
  1113.                                 break;
  1114.                         default:
  1115.                                 windputc(eras?' ':c);
  1116.                                 col++;
  1117.                                 break;
  1118.                         }
  1119.                         break;
  1120.                 default:
  1121.                         windputc(eras?' ':c);
  1122.                         col++;
  1123.                         break;
  1124.                 }
  1125.         }
  1126. }
  1127.  
  1128. /* Allow roaming around and changing of parameter values. */
  1129. editdata(name,data)
  1130. char *name;
  1131. char *data;     /* vmem format */
  1132. {
  1133.         int c, n;
  1134.  
  1135.         windclear();
  1136.         windrefresh();
  1137.         /* enable all the parameters */
  1138.         for ( n=0; P[n].p_name != NULL; n++ )
  1139.                 enableparm(n);
  1140.  
  1141.         /* Take the voice data and put it into P */
  1142.         (*Datain)(data);
  1143.  
  1144.         Prow = Pcol = 0;
  1145.         Changed = 0;
  1146.         Redraw = 1;
  1147.         gotoparm(CH_RIGHT);     /* Get to the first parameter */
  1148.         for ( ;; ) {
  1149.                 if ( Redraw ) {
  1150.                         showallparms(name);
  1151.                         Redraw = 0;
  1152.                 }
  1153.                 windgoto(Prow,Pcol);
  1154.                 windrefresh();
  1155.                 c = mouseorkey();
  1156.                 if ( c == MOUSE ) {
  1157.                         editmouse();
  1158.                         continue;
  1159.                 }
  1160.                 switch(c){
  1161.                 case CH_RIGHT:
  1162.                 case CH_UP:
  1163.                 case CH_DOWN:
  1164.                 case CH_LEFT:
  1165.                         gotoparm(c);
  1166.                         break;
  1167.                 case CH_REDRAW:
  1168.                         showallparms(name);
  1169.                         break;
  1170.                 case 'N':
  1171.                         /* Allow changing of voice name */
  1172.                         windgoto(0,5);
  1173.                         windstr("                ");
  1174.                         windgoto(0,6);
  1175.                         windrefresh();
  1176.                         windgets(Buff);
  1177.                         if ( Buff[0]!='\0' && Buff[0]!='\n' )
  1178.                                 (*Setnameof)(data,Buff);
  1179.                         showname(name=(*Nameof)(data));
  1180.                         Changed = 1;
  1181.                         break;
  1182.  
  1183.                 case CH_INC:
  1184.                         adjuparm(1);
  1185.                         break;
  1186.                 case CH_INC2:
  1187.                         adjuparm(4);
  1188.                         break;
  1189.                 case CH_INC3:
  1190.                         adjuparm(P[Parm].p_max - P[Parm].p_min);
  1191.                         break;
  1192.                 case CH_DEC:
  1193.                         adjuparm(-1);
  1194.                         break;
  1195.                 case CH_DEC2:
  1196.                         adjuparm(-4);
  1197.                         break;
  1198.                 case CH_DEC3:
  1199.                         adjuparm(P[Parm].p_min - P[Parm].p_max);
  1200.                         break;
  1201. #ifdef OLDSTUFF
  1202.                 case 'a':
  1203.                         sendaced(data);
  1204.                         playnote(0);
  1205.                         break;
  1206. #endif
  1207.                 case ' ':
  1208.                 case '\n':
  1209. #ifndef macintosh
  1210.                 case '\r':
  1211. #endif
  1212.                         if ( Changed ) {
  1213.                                 (*Dataout)(data);
  1214.                                 (*Sendedit)(data);
  1215.                         }
  1216.                         playnote(0);
  1217.                         break;
  1218.                 case '\033':
  1219.                 case '`':
  1220.                         allnotesoff();
  1221.                         break;
  1222.                 case 'q':
  1223.                 case EOF:
  1224.                         if ( Changed ) {
  1225.                                 (*Dataout)(data);
  1226.                                 (*Sendedit)(data);
  1227.                         }
  1228.                         return;
  1229.                 default:
  1230.                         break;
  1231.                 }
  1232.         }
  1233. }
  1234.  
  1235. adjuparm(incdec)
  1236. {
  1237.         int v, n;
  1238.  
  1239.         v = P[Parm].p_val + incdec;
  1240.         if ( v < (n=P[Parm].p_min) )
  1241.                 v = n;
  1242.         if ( v > (n=P[Parm].p_max) )
  1243.                 v = n;
  1244.         Changed = 1;
  1245.         showparam(Parm,1);      /* erase the old val */
  1246.         P[Parm].p_val = v;
  1247.         showparam(Parm,0);      /* show the new val */
  1248. }
  1249.  
  1250. editmouse()
  1251. {
  1252.         int row, col, thisparm;
  1253.  
  1254.         getmouse(&row,&col);
  1255.         thisparm = closeparm(row,col);
  1256.         if ( thisparm == Parm ) {
  1257.                 if ( statmouse() > 1 )
  1258.                         adjuparm(-1);   /* right button */
  1259.                 else if ( statmouse() == 1 ) /* added by mab - bug fix */
  1260.                         adjuparm(1);    /* left button */
  1261.         }
  1262.         else {
  1263.                 Parm = thisparm;
  1264.                 Prow = P[Parm].p_vrow;
  1265.                 Pcol = P[Parm].p_vcol;
  1266.         }
  1267. }
  1268.  
  1269. /* closeparm - Find the closest parameter */
  1270. closeparm(row,col)
  1271. {
  1272.         register struct paraminfo *pp;
  1273.         register int n;
  1274.         int dist, mindist, minparm, dr, dc;
  1275.  
  1276.         minparm = 0;
  1277.         mindist = Rows + Cols;
  1278.         for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  1279.                 if ( pp->p_flags != 0 )
  1280.                         continue;
  1281.                 if ( (dr=row-(pp->p_vrow)) < 0 )
  1282.                         dr = -dr;
  1283.                 if ( (dc=col-(pp->p_vcol)) < 0 )
  1284.                         dc = -dc;
  1285.                 if ( (dist=dr*dr+dc*dc) < mindist ) {
  1286.                         minparm = n;
  1287.                         mindist = dist;
  1288.                 }
  1289.         }
  1290.         return(minparm);
  1291. }
  1292.  
  1293. /* playnote - play the 'auto' note */
  1294. playnote(i)
  1295. {
  1296.         int pitch, vol, dur, chan;
  1297.         long endtime;
  1298.  
  1299.         pitch = getval("autopitch");
  1300.         if(i == 0) { /* called from inside edit-mode */
  1301.                 chan = getval("autochan");
  1302.         } else { /* called from the top level */
  1303.                 chan = Channel;
  1304.         }
  1305.         vol = getval("autovol");
  1306.         dur = getval("autodur");
  1307.         endtime = milliclock() + dur * 100;
  1308.         midinote(1,chan,pitch,vol);
  1309.         while ( milliclock() < endtime )
  1310.                 ;
  1311.         midinote(0,chan,pitch,vol);
  1312. }
  1313.  
  1314. /* gotoparm - search for the next parameter in the specified direction */
  1315. gotoparm(dir)
  1316. {
  1317.         int n, k, inc, pm, orig, r = Prow, c = Pcol;
  1318.  
  1319.         if ( dir==CH_LEFT || dir==CH_RIGHT ) {
  1320.                 if ( dir==CH_LEFT )
  1321.                         c--;
  1322.                 else
  1323.                         c++;
  1324.                 orig = c;
  1325.                 inc = 0;
  1326.                 pm = -1;
  1327.                 /* look up and down, alternately */
  1328.                 for ( n=2*Rows; n>0; n-- ) {
  1329.                         r += (pm * inc++);
  1330.                         pm = -pm;
  1331.                         if ( r < 0 || r >= Rows )
  1332.                                 continue;
  1333.                         if ( dir == CH_LEFT ) {
  1334.                                 for ( c=orig; c>=0; c-- ) {
  1335.                                         if ( parmat(r,c) )
  1336.                                                 return;
  1337.                                 }
  1338.                         }
  1339.                         else {
  1340.                                 for ( c=orig; c<Cols; c++ ) {
  1341.                                         if ( parmat(r,c) )
  1342.                                                 return;
  1343.                                 }
  1344.                         }
  1345.                 }
  1346.                 return;
  1347.         }
  1348.         if ( dir==CH_DOWN || dir==CH_UP ) {
  1349.                 if ( dir==CH_DOWN )
  1350.                         r++;
  1351.                 else
  1352.                         r--;
  1353.                 orig = c;
  1354.                 while ( r >= 0 && r < Rows ) {
  1355.                         /* look toward both sides at the same time */
  1356.                         inc = 0;
  1357.                         pm = -1;
  1358.                         for ( k=2*Cols; k>0; k-- ) {
  1359.                                 c += (pm * inc++);
  1360.                                 pm = -pm;
  1361.                                 if ( c < 0 || c >= Cols )
  1362.                                         continue;
  1363.                                 if ( parmat(r,c) )
  1364.                                         return;
  1365.                         }
  1366.                         if ( dir==CH_DOWN )
  1367.                                 r++;
  1368.                         else
  1369.                                 r--;
  1370.                         c = orig;
  1371.                 }
  1372.                 return;
  1373.         }
  1374. }
  1375.  
  1376. /* paramat - return non-zero if a parameter value is at position r,c */
  1377. parmat(r,c)
  1378. register int r, c;
  1379. {
  1380.         register int n;
  1381.         register struct paraminfo *pp;
  1382.  
  1383.         for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) {
  1384.                 if ( pp->p_flags != 0 )
  1385.                         continue;
  1386.                 if ( pp->p_vrow==r && pp->p_vcol==c ) {
  1387.                         Prow = r;
  1388.                         Pcol = c;
  1389.                         Parm = n;
  1390.                         return(1);
  1391.                 }
  1392.         }
  1393.         return(0);
  1394. }
  1395.  
  1396. /* parmindex - return index (in P) of a given parameter name. */
  1397. parmindex(name)
  1398. char *name;
  1399. {
  1400.         int n;
  1401.         char *s;
  1402.  
  1403.         for ( n=0; (s=P[n].p_name) != NULL; n++ ) {
  1404.                 if ( strcmp(s,name) == 0 )
  1405.                         return(n);
  1406.         }
  1407.         sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!",name);
  1408.         windstr(Buff);
  1409.         windrefresh();
  1410.         return(-1);
  1411. }
  1412.  
  1413. setval(name,v)
  1414. char *name;
  1415. {
  1416.         int n;
  1417.  
  1418.         if ( (n=parmindex(name)) < 0 )
  1419.                 return;
  1420.         P[n].p_val = v;
  1421. }
  1422.  
  1423. getval(name)
  1424. char *name;
  1425. {
  1426.         int n;
  1427.  
  1428.         if ( (n=parmindex(name)) < 0 )
  1429.                 return(0);
  1430.         return(P[n].p_val);
  1431. }
  1432.  
  1433. enableparm(n)
  1434. {
  1435.         if ( P[n].p_flags != 0 )
  1436.                 P[n].p_flags = 0;
  1437. }
  1438.  
  1439. disableparm(n)
  1440. {
  1441.         if ( P[n].p_flags == 0 )
  1442.                 P[n].p_flags = 1;
  1443. }
  1444.  
  1445. midinote(onoff,chan,pitch,vol)
  1446. {
  1447.         sendmidi( ((onoff==1)?(0x90):(0x80)) | ((chan-1)&0xf) );
  1448.         sendmidi( pitch & 0x7f );
  1449.         sendmidi( vol & 0x7f );
  1450. }
  1451.  
  1452. static char Nbuff[16];
  1453.  
  1454. char *visnum(v)
  1455. {
  1456.         sprintf(Nbuff,"%d",v);
  1457.         return(Nbuff);
  1458. }
  1459. char *visonoff(v)
  1460. {
  1461.         if ( v==0 )
  1462.                 return("off");
  1463.         else
  1464.                 return("on");
  1465. }
  1466.  
  1467. char *
  1468. bankvoice(voice)
  1469. {
  1470.         int offset = Libbank * Nvoices * Voicesize + voice * Voicesize;
  1471.         return(Libdata + offset);
  1472. }
  1473.