home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Sample Code / Music Architecture / Mixed Bag / •Instrument Editor / Instrument Editor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-09  |  26.0 KB  |  1,349 lines  |  [TEXT/KAHL]

  1. /*
  2.  * file: Instrument Editor.c
  3.  *
  4.  * started 22 March 1992
  5.  * david van brink
  6.  *
  7.  */
  8.  
  9.  
  10. /*--------------------------
  11.     Inclusions
  12. --------------------------*/
  13.  
  14. #include <Memory.h>
  15. #include <QuickDraw.h>
  16. #include <Windows.h>
  17. #include <Dialogs.h>
  18. #include <OSUtils.h>
  19. #include <Errors.h>
  20. #include <Resources.h>
  21. #include <Timer.h>
  22.  
  23. //#include <MIDI.h>
  24.  
  25. #include "BigEasy2.h"
  26. #include "BigEasyGrafish.h"
  27. #include "BigEasyTextish.h"
  28. #include "BigEasyControls.h"
  29. #include "BigEasyDialogs.h"
  30. #include "BigEasyUtils.h"
  31.  
  32. #include "Instrument Editor Controls.h"
  33. #include "IE PrintUtilities.h"
  34.  
  35. #define globals
  36. #include "More IE Routines.h"
  37. #include "Instrument Editor.h"
  38. #include "Instrument Editor Filing.h"
  39. #include "Instrument Editor Menus.h"
  40.  
  41. /*--------------------------
  42.     Limits and Konstants
  43. --------------------------*/
  44.  
  45. #define SignIt(x) ( (x)?1:-1)
  46.  
  47.  
  48. /*--------------------------
  49.     Prototypes
  50. --------------------------*/
  51. static void OpenAWindow(void);
  52.  
  53. static void KeyDoc(short n,short key,short code,short mods);
  54. static short CloseDoc(short n);
  55. static void ActivateDoc(short n);
  56. static void DeactivateDoc(short n);
  57. static void IdleDoc(short n,Boolean front);
  58. static void LetsQuit(short n,short menuItem,short menuRef);
  59. static void NameInstrumentDoc(short n, short menuItem, short menuRef);
  60. static void RandomizeKnobsDoc(short n, short menuItem, short menuRef);
  61. static void ShowCPULoad(short n, short menuItem, short menuRef);
  62. static void GetInstrumentDoc(short n, short menuItem, short menuRef);
  63. static void GetROMInstrumentsDoc(short n, short menuItem, short menuRef);
  64. static void InitVars(void);
  65. static void InstrumentSliderValueDrawProc(EasyControl ec);
  66.  
  67. static void MoveDoc(short n);
  68. static void AddToList(TDoc *d, InstrumentDataHandle iH);
  69.  
  70. Boolean CheckBit(unsigned long *t, long bit);
  71.  
  72.  
  73. static void About(void);
  74. static void SliderValueProc(EasyControl ec);
  75. pascal ComponentResult EditorMusicReadHook(MusicMIDIPacket *mp, long refCon);
  76. static void OpenSomeSynth(short n, short item,short ref);
  77.  
  78. static pascal void JunkTask(void);
  79. static long GetCPUTime(void);
  80.  
  81. static unsigned long gUnloadedCPUTime;
  82.  
  83.  
  84. /*--------------------------
  85.     More bits
  86. --------------------------*/
  87. static tSliderStyle aSliderStyle =
  88.     {
  89.     longNum,
  90.     kSliderWidth,13,
  91.     kSliderWidth,13,
  92.     InstrumentSliderValueDrawProc
  93.     };
  94.  
  95. static unsigned long gCPUUnloadedTime;
  96.  
  97.  
  98. /*--------------------------
  99.     Computer Programs
  100. --------------------------*/
  101.  
  102.  
  103.  
  104. void SliderValueProc(EasyControl ec)
  105.     {
  106.     long value;
  107.     long id;
  108.     TDoc *d;
  109.  
  110.     d = (void *)GetEasyControlRefcon(ec);
  111.     value = GetEasyControlValue(ec);
  112.     id = GetEasyControlID(ec);
  113.  
  114.     if(d->whichList == mInstrumentKnobs)
  115.         NASetKnob(d->na,d->nc,id + 1,value);
  116.     else if(d->whichList == mControllers)
  117.         NASetController(d->na,d->nc,id,value);
  118.     else
  119.         MusicSetKnob(d->ci,id + 1,value);
  120.     }
  121.  
  122.  
  123.  
  124.  
  125. void KeyDoc(short n,short key,short code,short mods)
  126.     {
  127.     Boolean x;
  128.     Rect r;
  129.     TDoc *d;
  130.     ComponentResult result;
  131.     long xBump,yBump,scale;
  132.     controlClickResult ccr;
  133.  
  134.     d = &gDoc[n - kFirstDocWindow];
  135.  
  136.     SetupSliderClipDoc(d);
  137.     KeyEasyControlList(d->ecl,key,mods,&ccr);
  138.     DoneSliderClipDoc(d);
  139.  
  140.  
  141.     switch(key)
  142.         {
  143.         case 31: //down arrow
  144.             xBump = 0;
  145.             yBump = 1;
  146. fly:
  147.             if(mods & optionKey)
  148.                 {
  149.                 if(mods & cmdKey)
  150.                     scale = 32000;
  151.                 else
  152.                     scale = 40;
  153.  
  154.                 xBump *= scale;
  155.                 yBump *= scale;
  156.  
  157.                 SetCtlValue(d->horizontalScroller,GetCtlValue(d->horizontalScroller) + xBump);
  158.                 SetCtlValue(d->verticalScroller,GetCtlValue(d->verticalScroller) + yBump);
  159.                 NewScrollDoc(d,true,nil);
  160.                 }
  161.             break;
  162.  
  163.         case 30: //up arrow
  164.             xBump = 0;
  165.             yBump = -1;
  166.             goto fly;
  167.  
  168.         case 29: //right arrow
  169.             xBump = 1;
  170.             yBump = 0;
  171.             goto fly;
  172.  
  173.         case 28: //left arrow
  174.             xBump = -1;
  175.             yBump = 0;
  176.             goto fly;
  177.  
  178.  
  179.  
  180.         case '[':
  181.             x = EasyDialogGetNumber("\pStore Instrument",
  182.                     "\pStore instrument in which instrument number:",
  183.                     &d->stashInstrument);
  184.             if(x)
  185.                 {
  186.                 GoWatch();
  187.                 result = MusicStoreInstrument(d->ci,d->part,d->stashInstrument);
  188.                 FlashResult(result);
  189.                 GoArrow();
  190.                 }
  191.             break;
  192.  
  193.         case ']':
  194.                 {
  195.                 ToneDescription td;
  196.                 ComponentResult result;
  197.  
  198.                 td.synthesizerType = d->sd.synthesizerType;
  199.                 td.instrumentNumber = d->recallInstrument;
  200.                 td.gmNumber = 0;
  201.                 if(d->sd.flags & (kSynthesizerGM | kSynthesizerGMSuperset))
  202.                     if(td.instrumentNumber <= 128)
  203.                         td.gmNumber = td.instrumentNumber;
  204.                 td.synthesizerName[0] = 0;
  205.                 td.instrumentName[0] = 0;
  206.                 result = NAPickInstrument(d->na,nil,"\pPick An Instrument:",&td,
  207.                         3,0,0,0);
  208.  
  209.                 if(!result)
  210.                     {
  211.                     x = true;
  212.                     MusicFindTone(d->ci,&td,&d->recallInstrument,nil);
  213.                     result = MusicSetInstrumentNumber(d->ci,d->part,d->recallInstrument);
  214.                     FlashResult(result);
  215.  
  216.                     result = MusicGetPartName(d->ci,d->part,d->instrumentName);
  217.                     FlashResult(result);
  218.                     UpdateSliderKnobs(d);
  219.                     DrawStats(d);
  220.                     }
  221.                 }
  222.  
  223.  
  224.  
  225.             break;
  226.  
  227.         case '=':
  228.         case '+':
  229.             d->recallInstrument = d->recallInstrument % d->sd.modifiableInstrumentCount + 1;
  230.         getNewOne:
  231.             result = MusicSetInstrumentNumber(d->ci,d->part,d->recallInstrument);
  232.             FlashResult(result);
  233.             result = MusicGetPartName(d->ci,d->part,d->instrumentName);
  234.             FlashResult(result);
  235.             DrawStats(d);
  236.             UpdateSliderKnobs(d);
  237.             break;
  238.  
  239.         case '-':
  240.         case '_':
  241.             d->recallInstrument = (d->recallInstrument + d->sd.modifiableInstrumentCount - 2)
  242.                     % d->sd.modifiableInstrumentCount + 1;
  243.             goto getNewOne;
  244.  
  245.  
  246.         }
  247.     }
  248.  
  249. short CloseDoc(short n)
  250. /*
  251.  * Close that window...
  252.  */
  253.     {
  254.     short x;
  255.     TDoc *d;
  256.     Boolean cancelClose;
  257.  
  258.     d = &gDoc[n - kFirstDocWindow];
  259.  
  260.     if(d->used && d->changed)
  261.         {
  262.         x = EasyDialogMessage(0,d->docSpec.name,"\pSave changes before closing this document?",
  263.                 kEasyDialogSaveDiscardCancel);
  264.         if(x == 2)
  265.             cancelClose = true;
  266.         else if(x == 0)
  267.             cancelClose = SaveDoc(n,0,0);
  268.         else
  269.             cancelClose = false;
  270.         }
  271.     else
  272.         cancelClose = false;
  273.  
  274.     if(!cancelClose)
  275.         {
  276.         UninstallWindow(n);
  277.  
  278.         CloseComponent(d->na);
  279.         DisposeEasyControlList(d->ecl);
  280.         d->ecl = 0;
  281.  
  282.         d->used = false;
  283.         gDocCount--;
  284.         }
  285.  
  286.     return cancelClose;
  287.     }
  288.  
  289. void FixUpMenus(TDoc *d)
  290.     /*
  291.      * Make menus suitable for document d,
  292.      * where d=nil means deactivate
  293.      */
  294.     {
  295.     short moreDocs;
  296.  
  297.     moreDocs = SignIt(gDocCount<kDocMax);
  298.  
  299.     SetMenuItem(mNew,moreDocs,0,0,nil);
  300.     SetMenuItem(mOpen,moreDocs,0,0,nil);
  301.  
  302.     if(d)
  303.         {
  304.         Point c;
  305.  
  306.         SetMenuItemRange(mFirstDocOnly,mLastDocOnly,1,0);
  307.         SetMenuItem(d->whichList,0,1,'•',0);
  308.         SetMenuItem(mSave,SignIt(d->changed || d->littleChanged),0,0,nil);
  309.  
  310.         c.h = c.v = 0;
  311.         if(!LGetSelect(true,&c,d->listH))
  312.             SetMenuItem(mSetInstrument,-1,0,0,0);
  313.         }
  314.     else
  315.         SetMenuItemRange(mFirstDocOnly,mLastDocOnly,-1,0);
  316.     }
  317.  
  318.  
  319.  
  320. void ActivateDoc(short n)
  321.     {
  322.     TDoc *d;
  323.     ComponentResult thisError;
  324.  
  325.     d = &gDoc[n - kFirstDocWindow];
  326.     FixUpMenus(d);
  327.  
  328.     if(d->listH)
  329.         LActivate(true,d->listH);
  330.     if(d->horizontalScroller)
  331.         {
  332.         HiliteControl(d->horizontalScroller,0);
  333.         HiliteControl(d->verticalScroller,0);
  334.         }
  335.  
  336.     thisError = NAUseDefaultMIDIInput(d->na,EditorMusicReadHook,(long)d,0);
  337.     }
  338.  
  339. void DeactivateDoc(short n)
  340.     {
  341.     TDoc *d;
  342.     ComponentResult thisError;
  343.  
  344.     d = &gDoc[n - kFirstDocWindow];
  345.     FixUpMenus(0);
  346.  
  347.     if(d->listH)
  348.     LActivate(false,d->listH);
  349.     if(d->horizontalScroller)
  350.         {
  351.         HiliteControl(d->horizontalScroller,254);
  352.         HiliteControl(d->verticalScroller,254);
  353.         }
  354.     thisError = NALoseDefaultMIDIInput(d->na);
  355.     FlashResult(thisError);
  356.     thisError = NAResetNoteChannel(d->na,d->nc);
  357.     FlashResult(thisError);
  358.  
  359.     d->controllersDirty = true;
  360.     }
  361.  
  362. void IdleDoc(short n,Boolean front)
  363.     {
  364.     TDoc *d;
  365.     ComponentResult thisError;
  366.  
  367.     d = &gDoc[n - kFirstDocWindow];
  368.  
  369.     PaintKeyboardVector(&d->kd,d->keyVel);
  370.     if(d->whichList == mControllers
  371.             && d->controllersDirty)
  372.         UpdateSliderKnobs(d);
  373.  
  374.     SetupSliderClipDoc(d);
  375.     IdleEasyControlList(d->ecl);
  376.     DoneSliderClipDoc(d);
  377.  
  378.         {
  379.         Point p;
  380.         short mods;
  381.  
  382.         GetMouse(&p);
  383.         mods = GetModKeys();
  384.         if(PtInRect(p,&d->visibleSliderBounds) && (mods & optionKey))
  385.             GoCursor(128);
  386.         else
  387.             GoArrow();
  388.         }
  389.     }
  390.  
  391.  
  392.  
  393.  
  394. typedef struct
  395.     {
  396.     short number;
  397.     Str31 name;
  398.     } XX;
  399.  
  400. XX dControllerNames[] =
  401.     {
  402.     kControllerModulationWheel,"\pMod",
  403.     kControllerBreath,"\pBreath",
  404.     kControllerFoot,"\pFoot",
  405.     kControllerPortamentoTime,"\pPortamento Time",
  406.     kControllerVolume,"\pVolume",
  407.     kControllerBalance,"\pBalance",
  408.     kControllerPan,"\pPan",
  409.     kControllerExpression,"\pExpression",
  410.     kControllerPitchBend,"\pPitch Bend",
  411.     kControllerAfterTouch,"\pAfter Touch",
  412.     kControllerSustain,"\pSustain",
  413.     kControllerPortamento,"\pPortamento",
  414.     kControllerSostenuto,"\pSostenuto",
  415.     kControllerSoftPedal,"\pSoft Pedal",
  416.     91,"\pReverb",
  417.     kControllerTremolo,"\pTremolo",
  418.     kControllerChorus,"\pChorus",
  419.     kControllerCeleste,"\pCeleste",
  420.     kControllerPhaser,"\pPhaser",
  421.     -1,"\p"
  422.     };
  423.  
  424. void InstrumentSliderValueDrawProc(EasyControl ec)
  425.     {
  426.     long x;
  427.     TDoc *d;
  428.     short i;
  429.  
  430.     x = GetEasyControlValue(ec);
  431.     d = (void *)GetEasyControlRefcon(ec);
  432.  
  433.     for(i = 0; i<d->knobCount; i++)
  434.         {
  435.         if(ec == d->ec[i])
  436.             {
  437.             if(d->whichList == mInstrumentKnobs)
  438.                 DrawString( (*(d->ikdList))[i].name);
  439.             else if(d->whichList == mGlobalKnobs)
  440.                 DrawString( (*(d->gkdList))[i].name);
  441.             else
  442.                 {
  443.                 short j;
  444.                 short id;
  445.  
  446.                 id = GetEasyControlID(ec);
  447.  
  448.                 j = 0;
  449.                 while(1)
  450.                     {
  451.                     if(dControllerNames[j].number == id)
  452.                         {
  453.                         DrawString(dControllerNames[j].name);
  454.                         goto gotIt;
  455.                         }
  456.                     else if(dControllerNames[j].number < 0)
  457.                         goto missedIt;
  458.                     j++;
  459.                     }
  460.                 missedIt:
  461.                     DrawString("\pController ");
  462.                     DrawNum(id);
  463.                 gotIt:;
  464.                 }
  465.             DrawString("\p: ");
  466.             }
  467.         }
  468.     if(x == 0x7FFFffff)
  469.         DrawString("\p----");
  470.     else
  471.         DrawNum(x);
  472.     }
  473.  
  474.  
  475.  
  476. static short dMyColors[6] =
  477.     {
  478.     0,
  479.     PackColor555(60000,60000,60000),
  480.     PackColor555(10000,10000,10000),
  481.     PackColor555(24000,0,0),
  482.     0,
  483.     0
  484.     };
  485.  
  486.  
  487. void LetsQuit(short n,short menuItem,short menuRef)
  488.     {
  489.     short i;
  490.     #pragma unused (n,menuItem,menuRef)
  491.  
  492.     for(i = 0; i < kDocMax; i++)
  493.         if(gDoc[i].used)
  494.             CloseDoc(i + kFirstDocWindow);
  495.  
  496.     gQuitApp++;
  497.     }
  498.  
  499.  
  500.  
  501. void NameInstrumentDoc(short n, short menuItem, short menuRef)
  502.     {
  503.     DialogPtr dp;
  504.     short hit;
  505.     short itemType;
  506.     Rect itemRect;
  507.     Handle itemHandle;
  508.     TDoc *d;
  509.     Boolean x;
  510.     ComponentResult result;
  511.  
  512.     d = &gDoc[n - kFirstDocWindow];
  513.  
  514.     x = EasyDialogGetString("\pInstrument Name","\pNew Name:",d->instrumentName,31);
  515.     if(x)
  516.         {
  517.         DrawStats(d);
  518.         result = MusicSetPartName(d->ci,d->part,d->instrumentName);
  519.         FlashResult(result);
  520.         }
  521.     }
  522.  
  523. void RandomizeKnobsDoc(short n, short menuItem, short menuRef)
  524.     {
  525.     TDoc *d;
  526.     ComponentResult result;
  527.     short i;
  528.     long x;
  529.     long dummy;
  530.     KnobDescription *kd;
  531.  
  532.     d = &gDoc[n - kFirstDocWindow];
  533.  
  534.     for(i = 0; i < d->knobCount; i++)
  535.         {
  536.         if(Random() % 6 == 0)
  537.             {
  538.     result = 0;
  539.     #if 1
  540.             kd = &(*d->ikdList)[i];
  541.             x = kd->lowValue +
  542.                     ((unsigned long)Random())%(kd->highValue
  543.                     - kd->lowValue + 1);
  544.             result = MusicSetPartKnob(d->ci,d->part,i+1,x);
  545.     #endif
  546.             if(result)
  547.                 {
  548.                 FlashResult(result);
  549.                 goto goHome;
  550.                 }
  551.             Delay(5,&dummy);
  552.             }
  553.         }
  554. goHome:
  555.     UpdateSliderKnobs(d);
  556.     }
  557.  
  558.  
  559.  
  560. static void AddToList(TDoc *d, InstrumentDataHandle iH)
  561. /*
  562.  * Adds an instrument to the list. Assume ownership of this handle.
  563.  */
  564.     {
  565.     InstrumentData *id;
  566.     ComponentResult thisError;
  567.  
  568.     if(!iH)
  569.         goto goHome;
  570.  
  571.     HLock((Handle)iH);
  572.     id = *iH;
  573.  
  574.     GoBW();
  575.  
  576.     TextFont(3);
  577.     TextSize(9);
  578.     TextFace(0);
  579.  
  580.         {
  581.         Point a;
  582.         long sizz;
  583.  
  584.         a.h = 0;
  585.         a.v = LAddRow(1,-1,d->listH);
  586.         LSetCell(&(id->tone.instrumentName[1]),id->tone.instrumentName[0],
  587.                 a,d->listH);
  588.  
  589.         if(d->instrument[d->instrumentCount])
  590.             DisposeHandle((Handle)d->instrument[d->instrumentCount]);
  591.  
  592.         d->instrument[d->instrumentCount] = iH;
  593.         d->instrumentCount++;
  594.         }
  595.     d->changed = true;
  596.     FixUpMenus(d);
  597.  
  598. goHome:;
  599.     }
  600.  
  601. void SetInstrumentForDoc(TDoc *d,InstrumentDataHandle iH)
  602.     {
  603.     ComponentResult result;
  604.  
  605.     GoWatch();
  606.     result = MusicSetInstrument(d->ci,d->part,iH);
  607.     GoArrow();
  608.     FlashResult(result);
  609.     result = MusicGetPartName(d->ci,d->part,d->instrumentName);
  610.     FlashResult(result);
  611.     DrawStats(d);
  612.     UpdateSliderKnobs(d);
  613.     }
  614.  
  615. void SetInstrumentDoc(short n, short menuItem, short menuRef)
  616.     {
  617.     TDoc *d;
  618.     Cell c;
  619.     ComponentResult result;
  620.  
  621.     d = &gDoc[n - kFirstDocWindow];
  622.  
  623.     c.h = c.v = 0;
  624.     if(!LGetSelect(true,&c,d->listH))
  625.         goto goHome;
  626.  
  627.     SetInstrumentForDoc(d,d->instrument[c.v]);
  628. goHome:;
  629.     }
  630.  
  631.  
  632. void GetInstrumentDoc(short n, short menuItem, short menuRef)
  633.     {
  634.     TDoc *d;
  635.     InstrumentDataHandle iH;
  636.     ComponentResult thisError;
  637.  
  638.     d = &gDoc[n - kFirstDocWindow];
  639.  
  640.     GoWatch();
  641.     thisError = MusicGetInstrument(d->ci,d->part,&iH);
  642.     GoArrow();
  643.     FlashResult(thisError);
  644.  
  645.     if(thisError)
  646.         goto goHome;
  647.  
  648.     AddToList(d,iH);
  649. goHome:;
  650.     }
  651.  
  652.  
  653.  
  654. void ShowCPULoad(short n, short menuItem, short menuRef)
  655.     {
  656.     Str255 s;
  657.     Str63 nu;
  658.     long x;
  659.  
  660.     CopyPString(s,"\pOriginal time = ");
  661.     AnyBaseToPString(gUnloadedCPUTime,10,0,nu);
  662.     ConcatenatePStrings(s,nu);
  663.     ConcatenatePStrings(s,"\p, Loaded time = ");
  664.     x = GetCPUTime();
  665.     AnyBaseToPString(x,10,0,nu);
  666.     ConcatenatePStrings(s,nu);
  667.     ConcatenatePStrings(s,"\p. Percentage of CPU speed gone = ");
  668.  
  669.     x = 100 - gUnloadedCPUTime * 100L / x;
  670.     AnyBaseToPString(x,10,0,nu);
  671.     ConcatenatePStrings(s,nu);
  672.     ConcatenatePStrings(s,"\p.");
  673.  
  674.  
  675.     EasyDialogMessage(1,"\pCPU Loading",
  676.             s,kEasyDialogOkay);
  677.     }
  678.  
  679.  
  680. void UpdateSliderKnobs(TDoc *d)
  681. /*
  682.  * Requery the music component for all
  683.  * the knob/slider values
  684.  */
  685.     {
  686.     long x;
  687.     short i;
  688.     EasyControl ec;
  689.     long id;
  690.  
  691.     SetupSliderClipDoc(d);
  692.  
  693.  
  694.     for(i = 0; i < d->knobCount; i++)
  695.         {
  696.         ec = d->ec[i];
  697.         id = GetEasyControlID(ec);
  698.  
  699.         if(d->whichList == mInstrumentKnobs)
  700.             x = MusicGetPartKnob(d->ci,d->part,id+1);
  701.         else if(d->whichList == mControllers)
  702.             x = MusicGetController(d->ci,d->part,id);
  703.         else
  704.             x = MusicGetKnob(d->ci,id+1);
  705.  
  706.         FlashResult(x);
  707.         if((x & 0xFFFF0000) == 0x80000000)
  708.             goto goHome;
  709.  
  710.         TextFont(3);
  711.         TextSize(9);
  712.         SetEasyControlValue(ec,x);
  713.         }
  714. goHome:
  715.     d->controllersDirty = false;
  716.     DoneSliderClipDoc(d);
  717.     }
  718.  
  719.  
  720.  
  721. void MoveDoc(short n)
  722.     {
  723.     register TDoc *d;
  724.  
  725.     d = &gDoc[n - kFirstDocWindow];
  726.  
  727.     d->littleChanged = true;
  728.     }
  729.  
  730.  
  731.  
  732. void NewDocFromSaveRecord(short docNumber,TSaveRecord *sr,SynthMenuEntry *sme)
  733.     {
  734.     register TDoc *d;
  735.     Rect r,windowRect;
  736.     Rect allControls;
  737.     ComponentResult result;
  738.     short i,j;
  739.     EasyControl ec;
  740.     KnobDescription *kd;
  741.     SynthMenuEntry smell;
  742.  
  743.     if(!sme)
  744.         {
  745.         if(sr)
  746.             {
  747.             smell.synthType = sr->sr.synthType;
  748.             BlockMove(sr->sr.synthName,smell.synthName,32);
  749.             }
  750.         else
  751.             {
  752.             smell.synthType = 0;
  753.             smell.synthName[0] = 0;
  754.             }
  755.         sme = &smell;
  756.         }
  757.  
  758.     d = &gDoc[docNumber];
  759.  
  760. #if 0
  761.         {
  762.         char *w;
  763.         short i;
  764.         /*
  765.          * Clear the document to zeros
  766.          */
  767.         i = sizeof(TDoc);
  768.         w = (void *)d;
  769.         while(i--)
  770.             *w++ = 0;
  771.         }
  772. #endif
  773.  
  774.     d->changed = false;
  775.  
  776.     for(i = 0; i < kMaxInstruments; i++)
  777.         d->instrument[i] = 0;
  778.  
  779.     d->na = OpenDefaultComponent('nota',0);
  780.  
  781.  
  782.  
  783.     if(sr)
  784.         {
  785.         gStaggerWindows = false;
  786.         windowRect = sr->windowRect;
  787.  
  788.         d->everSaved = true;
  789.         d->sr = sr->sr;
  790.         d->littleChanged = false;
  791.         }
  792.     else
  793.         {
  794.         gStaggerWindows = true;
  795.         gStagStepX = 3;
  796.         gStagStepY = 2;
  797.         SetRect(&windowRect,10,30,625,460);
  798.  
  799.         CopyPString(d->docSpec.name,"\pUntitled");
  800.         d->everSaved = false;
  801.  
  802.         d->littleChanged = true;
  803.         }
  804.  
  805.  
  806.     d->w = InstallWindow(-(docNumber + kFirstDocWindow),d->docSpec.name,&windowRect,0,1,
  807.             DrawDoc,ClickDoc,KeyDoc,(void *)CloseDoc,
  808.             ActivateDoc,DeactivateDoc,IdleDoc);
  809.     SetWindowMoveProc(docNumber + kFirstDocWindow,MoveDoc);
  810.     SetWindowResizeProc(docNumber + kFirstDocWindow,ResizeDoc);
  811.  
  812.  
  813.         {
  814.         NoteRequest nr;
  815.         long index;
  816.         OSType synthType;
  817.     
  818.         nr.polyphony = 2;
  819.         nr.typicalPolyphony = 0x00010000;
  820.         result = NAStuffToneDescription(d->na,1,&nr.tone);
  821.         BlockMove(sme->synthName,nr.tone.synthesizerName,32);
  822.         nr.tone.synthesizerType = sme->synthType;
  823.         result = NANewNoteChannel(d->na,&nr,&d->nc);
  824.         FlashResult(result);
  825.         result = NAGetNoteChannelInfo(d->na,d->nc,&index,&d->part);
  826.         FlashResult(result);
  827.  
  828.         result = NAGetRegisteredMusicDevice(d->na,index,&synthType,nil,nil,&d->ci);
  829.         FlashResult(result);
  830.  
  831.         if(synthType != sme->synthType) //!!! note that this is in error, somehow
  832.             {
  833.             SysBeep(1);
  834.             SysBeep(1);
  835.             SysBeep(1);
  836.             }
  837.  
  838.  
  839.         d->sr.synthType = sme->synthType;
  840.         BlockMove(sme->synthName,d->sr.synthName,32);
  841.         }
  842.         
  843.  
  844. /*
  845.  * Since FlashResult will process the
  846.  * update for the window, we have to
  847.  * make harmless the update process.
  848.  */
  849.  
  850.     d->used = true;
  851.     d->ecl = NewEasyControlList(d->w,0);
  852.  
  853.     result = MusicGetDescription(d->ci,&d->sd);
  854.     FlashResult(result);
  855.  
  856.     d->instrumentKnobCount = MusicGetInstrumentKnobDescription(d->ci,0,nil);
  857.         {
  858.         KnobDescription *kd;
  859.         short i;
  860.  
  861.         d->ikdList = (KnobDescription **)NewHandle(sizeof(KnobDescription) * d->instrumentKnobCount);
  862.         HLock((Handle)d->ikdList);
  863.         kd = *d->ikdList;
  864.         for(i = 0; i < d->instrumentKnobCount; i++)
  865.             result = MusicGetInstrumentKnobDescription(d->ci,i+1,kd+i);
  866.         }
  867.  
  868.     d->globalKnobCount = MusicGetKnobDescription(d->ci,0,nil);
  869.         {
  870.         KnobDescription *kd;
  871.         short i;
  872.  
  873.         d->gkdList = (KnobDescription **)NewHandle(sizeof(KnobDescription) * d->globalKnobCount);
  874.         HLock((Handle)d->gkdList);
  875.         kd = *d->gkdList;
  876.         for(i = 0; i < d->globalKnobCount; i++)
  877.             result = MusicGetKnobDescription(d->ci,i+1,kd+i);
  878.         }
  879.  
  880.     d->controllerCount = 0;
  881.         {
  882.         short i;
  883.         for(i = 1; i <= 128; i++)
  884.             if(CheckBit(d->sd.controllers,i))
  885.                 d->controllerCount++;
  886.         }
  887.  
  888.  
  889.     d->whichList = mInstrumentKnobs;
  890.     d->knobCount = d->instrumentKnobCount;
  891.  
  892.         {
  893.         ToneDescription td;
  894.         long instrumentNumber;
  895.  
  896.         td.synthesizerType = 0;
  897.         td.synthesizerName[0] = 0;
  898.         td.instrumentName[0] = 0;
  899.         td.instrumentNumber = 0;
  900.         td.gmNumber = 1;
  901.  
  902.  
  903.         result = MusicFindTone(d->ci, &td, &instrumentNumber, nil);
  904.         FlashResult(result);
  905.  
  906.         result = MusicSetInstrumentNumber(d->ci,d->part,instrumentNumber);
  907.         FlashResult(result);
  908.         }
  909.  
  910.     result = MusicGetPartName(d->ci,d->part,d->instrumentName);
  911.     FlashResult(result);
  912.  
  913. /* end boguslike setup */
  914.  
  915.         {
  916.         short knobses;
  917.  
  918.         if(d->globalKnobCount > d->instrumentKnobCount)
  919.             knobses = d->globalKnobCount;
  920.         else
  921.             knobses = d->instrumentKnobCount;
  922.         if(knobses < 32)
  923.             knobses = 32;            /* for the controller list */
  924.  
  925.         /*
  926.          * allocate space for enough controls
  927.          */
  928.         d->ec = (void *)NewPtr(sizeof(easyControl)
  929.                 * knobses);
  930.         }
  931.  
  932.     d->stashInstrument = 1;
  933.     d->recallInstrument = 1;
  934.  
  935.  
  936.     MakeControlsFromKnobList(d,&allControls);
  937.  
  938.     d->visibleSliderBounds.top = d->visibleSliderBounds.bottom
  939.             = d->visibleSliderBounds.left = d->visibleSliderBounds.right = 0;
  940.     d->virtualSliderBounds= allControls;
  941.  
  942.     UpdateSliderKnobs(d);
  943.  
  944.     /*
  945.      * Add the scroll bars
  946.      */
  947.     r.top = r.left = -10;
  948.     r.bottom = r.right = -5;
  949.     d->horizontalScroller = NewControl(d->w,&r,"\p",false,0,0,1,scrollBarProc,0);
  950.     d->verticalScroller = NewControl(d->w,&r,"\p",false,0,0,1,scrollBarProc,0);
  951.     d->lastH = d->lastV = 0;
  952.  
  953.         {
  954.         Point a;
  955.         Rect cellBounds;
  956.         InstrumentDataHandle iH;
  957.     
  958.         cellBounds.top = cellBounds.left = 0;
  959.         cellBounds.right = 1;
  960.         cellBounds.bottom = 0;
  961.  
  962.         a.h = kInstrumentListWidth;
  963.         a.v = kInstrumentListCellHeight;
  964.         r.left = kInstrumentListLeft + 1;
  965.         r.right = kInstrumentListRight - 16;
  966.         r.top = kInstrumentListTop;
  967.         r.bottom = r.top + 10;
  968.         d->listH = LNew(&r,&cellBounds,a,0,d->w,false,false,false,true);
  969.  
  970.         d->instrumentCount = 0;
  971.  
  972.         if(sr)
  973.             {
  974.             i = 1;
  975.             do
  976.                 {
  977.                 iH = (InstrumentDataHandle)Get1Resource(kInstrumentListResType,i++);
  978.                 DetachResource((Handle)iH);
  979.                 if(iH)
  980.                     AddToList(d,iH);
  981.                 } while(iH);
  982.             }
  983.         }
  984.  
  985.     d->statBounds.left = kStatLeft+1;
  986.     d->statBounds.right = kStatRight-1;
  987.     d->statBounds.top = kStatTop;
  988.     d->statBounds.bottom = kStatBottom;
  989.  
  990.         {
  991.         Rect r;
  992.         r.left = kKeyboardLeft;
  993.         r.right = kKeyboardRight;
  994.         r.top = kKeyboardTop;
  995.         r.bottom = kKeyboardBottom;
  996.  
  997.         InitializeKeyboard(&d->kd,&r,kKeyboardOctaveCount,48);
  998.         }
  999.  
  1000.  
  1001.     gDocCount++;
  1002.  
  1003.         {
  1004.         Point a,b;
  1005.  
  1006.         a.h = b.h = windowRect.right - windowRect.left;
  1007.         a.v = b.v = windowRect.bottom - windowRect.top;
  1008.         ResizeDoc(docNumber + kFirstDocWindow,&a,&b,0);
  1009.         ShowWindow(d->w);
  1010.         }
  1011. goHome:;
  1012.     }
  1013.  
  1014. void About(void)
  1015.     {
  1016.     EasyDialogMessage(0,(StringPtr)0x910,
  1017.             "\pby David Van Brink",
  1018.             kEasyDialogOkay);
  1019.     }
  1020.  
  1021.  
  1022. void OpenSomeSynth(short n, short item,short ref)
  1023.     {
  1024.     short i;
  1025.  
  1026.     for(i = 0; i<kDocMax; i++)
  1027.         {
  1028.         if(!gDoc[i].used)
  1029.             {
  1030.             NewDocFromSaveRecord(i,nil,&(**gSynthListH).entry[item-1]);
  1031.             goto goHome;
  1032.             }
  1033.         }
  1034. goHome:;
  1035.     }
  1036. #define kSliderVertBump 33
  1037.  
  1038. Boolean CheckBit(unsigned long *t, long bit)
  1039.     {
  1040.     bit--;
  1041.  
  1042.     t += (bit / 32);
  1043.     bit &= 31;
  1044.     bit = 1L<<(31-bit);
  1045.     return ((*t) & bit) != 0;
  1046.     }
  1047.  
  1048. void MakeControlsFromKnobList(TDoc *d,Rect *outRect)
  1049.     {
  1050.     Rect allControls,r;
  1051.     short i;
  1052.     short j;
  1053.     KnobDescription *kd;
  1054.     EasyControl ec;
  1055.     ComponentResult result;
  1056.     short knobCount;
  1057.     short columnCount;
  1058.     short id;
  1059.  
  1060.  
  1061.     if(d->whichList == mInstrumentKnobs)
  1062.         d->knobCount = d->instrumentKnobCount;
  1063.     else if(d->whichList == mControllers)
  1064.         d->knobCount = d->controllerCount;
  1065.     else
  1066.         d->knobCount = d->globalKnobCount;
  1067.  
  1068.     knobCount = d->knobCount;
  1069.  
  1070.     SetRect(&allControls,0,0,0,0);
  1071.     ClipRect(&allControls);            /* kill drawing for a while */
  1072.  
  1073.     SetRect(&r,kDocMargin,kDocMargin,kSliderWidth + kDocMargin,kDocMargin + 14);
  1074.     kd = * (d->whichList == mInstrumentKnobs ? d->ikdList : d->gkdList);
  1075.  
  1076.     columnCount = 1;
  1077.     for(i = 0; i < knobCount; i++)
  1078.         {
  1079.         if((!(d->whichList == mControllers)) && ((kd->flags & kKnobGroupStart) && i))
  1080.             {
  1081.             OffsetRect(&r,r.right - r.left + kDocMargin,0);
  1082.             r.top = kDocMargin;
  1083.             r.bottom = r.top + 14;
  1084.             columnCount = 1;
  1085.             }
  1086.         else
  1087.             {
  1088.             columnCount++;
  1089.             if(columnCount > 20)
  1090.                 {
  1091.                 OffsetRect(&r,r.right - r.left + kDocMargin,0);
  1092.                 r.top = kDocMargin + kSliderVertBump;
  1093.                 r.bottom = r.top + 14;
  1094.                 columnCount = 2;
  1095.                 }
  1096.             }
  1097.         UnionRect(&allControls,&r,&allControls);
  1098.         if(d->whichList == mControllers)
  1099.             {
  1100.             short jj;
  1101.             jj = 0;
  1102.             for(id = 1; id <= 128; id++)
  1103.                 if(CheckBit(d->sd.controllers,id))
  1104.                     {
  1105.                     jj++;
  1106.                     if(jj == (i+1))
  1107.                         goto gotControl;
  1108.                     }
  1109.             id = 1;
  1110.             gotControl:
  1111.  
  1112.             ec = NewEasyControl(&sliderType,&r,0,&aSliderStyle,(long)d,id,0,d->ecl);
  1113.             }
  1114.         else
  1115.             ec = NewEasyControl(&sliderType,&r,0,&aSliderStyle,(long)d,i,0,d->ecl);
  1116.         d->ec[i] = ec;
  1117.  
  1118.         SetEasyControlValueProc(ec,(void *)SliderValueProc);
  1119.         SetEasyControlColors(d->ec[i],dMyColors);
  1120.  
  1121. //???        FlashResult(result);
  1122.         if(d->whichList == mControllers)
  1123.             {
  1124.             if(id == kControllerPitchBend)
  1125.                 SetEasyControlRange(ec,0,3<<8);        /* 3 semitones */
  1126.             else if(id == kControllerVolume)
  1127.                 SetEasyControlRange(ec,0,0x0001FFFF);    /* up to 4x max volume */
  1128.             else
  1129.                 SetEasyControlRange(ec,0,(127<<8) + 255);
  1130.             }
  1131.         else
  1132.             SetEasyControlRange(ec,kd->lowValue,kd->highValue);
  1133.  
  1134.         OffsetRect(&r,0,33);
  1135.         kd++;
  1136.         }
  1137.  
  1138.     allControls.bottom += 20;
  1139.     allControls.right += kDocMargin;
  1140.  
  1141.     *outRect = allControls;
  1142.  
  1143.     }
  1144.  
  1145.  
  1146. void InitVars()
  1147. /*
  1148.  * Called once at startup: yes, it
  1149.  * inits the vars.
  1150.  */
  1151.     {
  1152.     TDoc *d;
  1153.     ComponentResult result;
  1154.  
  1155.     gUnloadedCPUTime = GetCPUTime();
  1156.  
  1157. #ifdef rolledIn
  1158.     InstallFB01();
  1159. //    InstallDumbSynth();
  1160. #endif
  1161.  
  1162.     }
  1163.  
  1164. void FlashResult(ComponentResult result)
  1165.     {
  1166.     Str255 s,n;
  1167.     short x;
  1168.     GrafPort *oldPort;
  1169.  
  1170.     GetPort(&oldPort);
  1171.  
  1172.  
  1173.  
  1174.     x = result & 0x0000FFFF;
  1175.  
  1176.     if((result & 0xFFFF0000) == 0x80000000)
  1177.         {
  1178.         CopyPString(s,"\pError number ");
  1179.         AnyBaseToPString(x,10,0,n);
  1180.         ConcatenatePStrings(s,n);
  1181.         ConcatenatePStrings(s,"\p occurred.");
  1182.         
  1183.         EasyDialogMessage(0,"\pMusic Error",s,kEasyDialogOkay);
  1184.         }
  1185.  
  1186.     SetPort(oldPort);
  1187.     }
  1188.  
  1189.  
  1190. void Bootstrap()
  1191.     {
  1192.     short i;
  1193.  
  1194. /*** File Menu ***/
  1195.     InstallMenu("\pFile",nil,0);
  1196.     InstallMenuItem("\pOpen…/O",OpenDoc,mOpen);
  1197.     InstallMenuItem("\pClose/W",(void *)CloseDoc,-mClose);
  1198.     InstallMenuItem("\p(-",nil,0);
  1199.     InstallMenuItem("\pSave/S",(void *)SaveDoc,-mSave);
  1200.     InstallMenuItem("\pSave As…",(void *)SaveAsDoc,-mSaveAs);
  1201.     InstallQuitItem(LetsQuit,0);
  1202.  
  1203. /*** Edit Menu ***/
  1204.     InstallEditMenu(nil,nil,nil,nil,nil);
  1205.  
  1206. /*** Synth Menu ***/
  1207.     gSynthListH = GetSynthesizerList();
  1208.     InstallMenu("\pSynthesizers",nil,0);
  1209.     for(i = 0; i < (**gSynthListH).synthCount; i++)
  1210.         {
  1211.         unsigned char s[40];
  1212.         CopyPString(s,(**gSynthListH).entry[i].synthName);
  1213.         if(!s[0])
  1214.             {
  1215.             s[0] = 1;
  1216.             s[1] = 'x';
  1217.             }
  1218.  
  1219.         if(i < 9)
  1220.             {
  1221.             s[s[0]+1] = '/';
  1222.             s[s[0]+2] = '1' + i;
  1223.             s[0] += 2;
  1224.             }
  1225.         InstallMenuItem( s,OpenSomeSynth,mNew);
  1226.         }
  1227.  
  1228. /* Instruments & Knobs Menu */
  1229.     InstallMenu("\pInstruments",nil,0);
  1230.     InstallMenuItem("\pName Instrument…/N",NameInstrumentDoc,-mNameInstrument);
  1231.     InstallMenuItem("\pAdd Instrument To List/A",GetInstrumentDoc,-mGetInstrument);
  1232.     InstallMenuItem("\pGet Instrument From List/G",SetInstrumentDoc,-mSetInstrument);
  1233.     InstallMenuItem("\p(-",0,0);
  1234.     InstallMenuItem("\pShow Instrument Knobs/¡",DoInstrumentKnobs,-mInstrumentKnobs);
  1235.     InstallMenuItem("\pShow Global Knobs/™",DoGlobalKnobs,-mGlobalKnobs);
  1236.     InstallMenuItem("\pShow Controllers/£",DoControllers,-mControllers);
  1237.     InstallMenuItem("\p(-",nil,0);
  1238.     InstallMenuItem("\pRandomize Instrument Knobs/K",RandomizeKnobsDoc,-mRandomizeKnobs);
  1239.     InstallMenuItem("\pDefault Instrument Knobs/D",SetDefaultInstrumentDoc,-mTestDoc);
  1240.  
  1241.  
  1242. /*** Tests Menu ***/
  1243.     InstallMenu("\pTests",nil,0);
  1244.     InstallMenuItem("\pPlay Pitchbend Scale",PitchBendDoc,-mPitchbendDoc);
  1245.     InstallMenuItem("\pPlay µTonal Scale",MicrotoneDoc,-mMicrotoneDoc);
  1246.     InstallMenuItem("\pNotes On",NotesOnDoc,-mTestDoc);
  1247.     InstallMenuItem("\pNotes Off",NotesOffDoc,-mTestDoc);
  1248.  
  1249. /*** Special Menu ***/
  1250.     InstallMenu("\pSpecial",nil,0);
  1251.     InstallMenuItem("\pCPU Load…/L",ShowCPULoad,mCPULoad);
  1252.     InstallMenuItem("\p(-",0,0);
  1253.     InstallMenuItem("\pSet Master Tuning",SetMasterTuneDoc,-mTestDoc);
  1254.     InstallMenuItem("\pSet Master Tuning",SetMasterTuneDoc,-mTestDoc);
  1255.  
  1256.  
  1257.  
  1258.         {
  1259.         Str63 s;
  1260.  
  1261.         CopyPString(s,"\pAbout ");
  1262.         ConcatenatePStrings(s,(StringPtr)0x910);
  1263.         ConcatenatePStrings(s,"\p…");
  1264.         SetAbout(s,0,About);
  1265.         }
  1266.  
  1267.     SetMasterOpenDocProc(OpenDocSpec);
  1268.     SetMasterQuitAppProc((void *)LetsQuit);
  1269.  
  1270.     InitVars();
  1271.     }
  1272.  
  1273. void Hatstrap()
  1274. /*
  1275.   * clean up
  1276.   */
  1277.     {
  1278.     }
  1279.  
  1280.  
  1281.  
  1282. pascal ComponentResult EditorMusicReadHook(MusicMIDIPacket *mp, long refCon)
  1283.     {
  1284.     ComponentInstance ci;
  1285.     unsigned short x;
  1286.     TDoc *d;
  1287.  
  1288.     d = (TDoc *)refCon;
  1289.  
  1290.     ci = d->ci;
  1291.  
  1292.     x = mp->data[0] & 0xF0;
  1293.     if(x == 0x80)
  1294.         {
  1295.         NAPlayNote(d->na,d->nc,mp->data[1],0);
  1296.         d->keyVel[mp->data[1]] = 0;
  1297.         }
  1298.     else if(x == 0x90)
  1299.         {
  1300.         NAPlayNote(d->na,d->nc,mp->data[1],mp->data[2]);
  1301.         d->keyVel[mp->data[1]] = mp->data[2];
  1302.         }
  1303.     else if(x == 0xE0)
  1304.         {
  1305.         NASetController(d->na,d->nc,kControllerPitchBend,
  1306.                 (((mp->data[2]<<7) | mp->data[1]) - 0x2000) >> 4 );
  1307.         d->controllersDirty = true;
  1308.         }
  1309.  
  1310.     return noErr;
  1311.     }
  1312.  
  1313.  
  1314. pascal void JunkTask(void)
  1315.     {
  1316.     }
  1317.  
  1318.  
  1319.  
  1320. long GetCPUTime(void)
  1321. /*
  1322.  * return the number of uSec for
  1323.  * some fixed little task here.
  1324.  */
  1325.     {
  1326.     TMTask tmTask;
  1327.     register long tot,x;
  1328.     short i;
  1329.  
  1330.     tot = 0;
  1331.  
  1332.     for(i = 0; i< 4; i++)
  1333.         {
  1334.  
  1335.         tmTask.tmAddr = (TimerUPP)JunkTask;
  1336.         tmTask.tmWakeUp = 0;
  1337.         tmTask.tmReserved = 0;
  1338.         InsXTime((void *)&tmTask);
  1339.         PrimeTime((void *)&tmTask,-(0x7FFFffff));
  1340.     
  1341.         x = 1000000;
  1342.         while(x--);
  1343.         RmvTime((void *)&tmTask);
  1344.         tot += tmTask.tmCount + (0x7FFFffff);
  1345.         }
  1346.  
  1347.     return tot;
  1348.     }
  1349.