home *** CD-ROM | disk | FTP | other *** search
/ MacWorld UK 2001 December / MW_UK_2001_12.iso / OS X Heaven / TimestretchVisualizer.dmg / Timestretch-Visualizer.bundle / Contents / Resources / notes next >
Encoding:
Text File  |  2001-10-21  |  25.3 KB  |  906 lines

  1. /*
  2.     File:        iTunesXPlugIn.c
  3.  
  4.     Contains:    visual plug-in for iTunes on Mac OS X
  5.         
  6.     Written by:     Developer Technical Support
  7.  
  8.     Copyright:    Copyright © 2001 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.             You may incorporate this Apple sample source code into your program(s) without
  11.             restriction. This Apple sample source code has been provided "AS IS" and the
  12.             responsibility for its operation is yours. You are not permitted to redistribute
  13.             this Apple sample source code as "Apple sample source code" after having made
  14.             changes. If you're going to re-distribute the source, we require that you make
  15.             it clear in the source that the code was descended from Apple sample source
  16.             code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                         6/6/01       KG       moved to project builder on Mac OS X
  20.                         4/17/01    DTS     first checked in.
  21. */
  22.  
  23. #include "TDeepFractal.h"
  24.  
  25.  
  26. #define QDMP_FLAG    1     // 0 != use direct pixmap access
  27.  
  28.  
  29. #include "QDMP.h"
  30. #include "iTunesVisualAPI.h"
  31.  
  32.  
  33. #define kTVisualPluginName                "\piTunesXPlugIn"
  34. #define    kTVisualPluginCreator            'hook'
  35.  
  36. #define    kTVisualPluginMajorVersion        1
  37. #define    kTVisualPluginMinorVersion        0
  38. #define    kTVisualPluginReleaseStage        finalStage
  39. #define    kTVisualPluginNonFinalRelease    0
  40.  
  41. enum
  42. {
  43.         kColorSettingID=3,
  44.     kFlashSettingID=4,
  45.         kOKSettingID=5
  46. };
  47.  
  48.  
  49. typedef struct VisualPluginData {
  50.     void *                appCookie;
  51.     ITAppProcPtr        appProc;
  52.  
  53.     ITFileSpec            pluginFileSpec;
  54.     
  55.     CGrafPtr            destPort;
  56.     Rect                destRect;
  57.     OptionBits            destOptions;
  58.     UInt32                destBitDepth;
  59.  
  60.     RenderVisualData    renderData;
  61.     UInt32                renderTimeStampID;
  62.     
  63.     ITTrackInfo            trackInfo;
  64.     ITStreamInfo        streamInfo;
  65.  
  66.     Boolean                playing;
  67.     Boolean                padding[3];
  68.  
  69. //    Plugin-specific data
  70.     UInt8                minLevel[kVisualMaxDataChannels];        // 0-128
  71.     UInt8                maxLevel[kVisualMaxDataChannels];        // 0-128
  72.  
  73.     UInt8                min,max;
  74.  
  75.     GWorldPtr            offscreen;
  76.     TDeepFractal             *myfractal;
  77.        
  78. } VisualPluginData;
  79.  
  80.  
  81.  
  82. #if QDMP_FLAG
  83. #define SET_PIXEL(pm,h,v,c) \
  84.             QDMP_Set_Pixel(pm,h,v,c);
  85. #else
  86. #define SET_PIXEL(pm,h,v,c) \
  87.             { RGBForeColor(c);MoveTo(h,v);Line(1,0);}
  88. #endif
  89.  
  90. /**\
  91. |**|    local (static) globals
  92. \**/
  93.  
  94. static Boolean    gColorFlag = true;
  95. static Boolean    gFlashFlag = false;
  96.  
  97. static CGrafPtr    gSavePort;
  98. static GDHandle    gSaveDevice;
  99. static SInt16    gLine = 0;
  100.  
  101. /**\
  102. |**|    exported function prototypes
  103. \**/
  104. extern "C" {
  105. extern OSStatus iTunesPluginMainMachO(OSType message,PluginMessageInfo *messageInfo,void *refCon);
  106. }
  107. /**\
  108. |**|    static functions
  109. \**/
  110.  
  111. //    MemClear
  112. static void MemClear(LogicalAddress dest,SInt32 length)
  113. {
  114.     register unsigned char    *ptr;
  115.  
  116.     ptr = (unsigned char*) dest;
  117.     
  118.     while (length-- > 0)
  119.         *ptr++ = 0;
  120. }
  121.  
  122. // ProcessRenderData
  123.  
  124. static void ProcessRenderData(VisualPluginData *visualPluginData,const RenderVisualData *renderData)
  125. {
  126.  
  127.     SInt16        index;
  128.     SInt32        channel;
  129.  
  130.     if (renderData == nil)
  131.     {
  132.         MemClear(&visualPluginData->renderData,sizeof(visualPluginData->renderData));
  133.         return;
  134.     }
  135.  
  136.     visualPluginData->renderData = *renderData;
  137.     
  138.     for (channel = 0;channel < renderData->numSpectrumChannels;channel++)
  139.     {
  140.         visualPluginData->minLevel[channel] = 
  141.             visualPluginData->maxLevel[channel] = 
  142.             renderData->spectrumData[channel][0];
  143.  
  144.         for (index = 1; index < kVisualNumSpectrumEntries; index++)
  145.         {
  146.             UInt8        value;
  147.             
  148.             value = renderData->spectrumData[channel][index];
  149.  
  150.             if (value < visualPluginData->minLevel[channel])
  151.                 visualPluginData->minLevel[channel] = value;
  152.             else if (value > visualPluginData->maxLevel[channel])
  153.                 visualPluginData->maxLevel[channel] = value;
  154.         }
  155.     }
  156. }
  157.  
  158. // GetPortCopyBitsBitMap
  159. //
  160. static BitMap* GetPortCopyBitsBitMap(CGrafPtr port)
  161. {
  162.     BitMap*        destBMap;
  163.  
  164. #if ACCESSOR_CALLS_ARE_FUNCTIONS
  165.     destBMap = (BitMap*)GetPortBitMapForCopyBits(port);
  166. #else
  167.   #if OPAQUE_TOOLBOX_STRUCTS
  168.     PixMapHandle    pixMap;
  169.     
  170.     pixMap        = GetPortPixMap(port);
  171.     destBMap    = (BitMap*) (*pixMap);
  172.   #else
  173.     destBMap    = (BitMap*) &((GrafPtr)port)->portBits;
  174.   #endif
  175. #endif
  176.     return destBMap;
  177. }
  178.  
  179. static const RGBColor gLandColors[] = {
  180.     {0x0000,0x0000,0x4000},    // dark blue
  181.     {0x4000,0x4000,0xC000},    // lite blue
  182.  
  183.     {0x0000,0x8000,0x0000},    // green
  184.     {0x4000,0xC000,0x4000},    // lite green
  185.     {0xB000,0x6000,0x4000},    // brown
  186.  
  187.     {0x8000,0x4000,0x2000},    // dark brown
  188.     {0x4000,0x4000,0x4000},    // gray
  189.     {0xC000,0xC000,0xC000}    // lt gray
  190. };
  191.  
  192. static void UInt8ToColorRGB(const UInt8 pValue,RGBColor* pRGBColorPtr)
  193. {
  194.     if (nil == pRGBColorPtr)
  195.         return;
  196.  
  197.     if (gColorFlag)
  198.     {
  199.         UInt8 hiValue = pValue / 32;
  200.         UInt8 nextValue = (hiValue + 1);
  201.  
  202.         if (nextValue >= 8) nextValue = hiValue;
  203.  
  204.         *pRGBColorPtr = QDMP_Mix_RGBColors(gLandColors[hiValue],gLandColors[nextValue],pValue / 32.0f);
  205.     }
  206.     else
  207.     {
  208.         pRGBColorPtr->red = pRGBColorPtr->green = pRGBColorPtr->blue = (pValue << 8) + pValue;
  209.     }
  210. }
  211.  
  212. static void _Erase(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect,Boolean onlyUpdate)
  213. {
  214.         #pragma unused(visualPluginData,destPort,destRect,onlyUpdate)
  215. }
  216.  
  217. static void _Draw(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect,Boolean onlyUpdate)
  218. {
  219.     Rect        srcRect;
  220.  
  221.     if ((nil == destPort) || (nil == destRect) ||
  222.         (nil == visualPluginData->offscreen))
  223.         return;
  224.  
  225.     srcRect    = *destRect;
  226.     OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
  227.  
  228.     if (false == onlyUpdate)
  229.     {
  230.         PixMapHandle    pixMapHdl = GetGWorldPixMap(visualPluginData->offscreen);
  231.  
  232.         if (!pixMapHdl || !*pixMapHdl)
  233.             return;
  234.  
  235.         SetGWorld(visualPluginData->offscreen,nil);
  236.  
  237.         gLine++;
  238.         if ((gLine < srcRect.top) || (gLine >= srcRect.bottom))
  239.             gLine = srcRect.top;
  240.  
  241.         // Update our offscreen pixmap
  242.         if (gFlashFlag)
  243.         {
  244.             RGBColor    foreColor;
  245.             Rect        tRect = srcRect;
  246.  
  247.             if (gColorFlag)
  248.                 UInt8ToColorRGB(visualPluginData->maxLevel[1],&foreColor);
  249.             else
  250.             {
  251.                 foreColor.red = foreColor.green = ((UInt16) visualPluginData->maxLevel[1] << 9);
  252.                 foreColor.blue = ((UInt16)visualPluginData->maxLevel[0] << 9);
  253.             }
  254.  
  255.             RGBForeColor(&foreColor);
  256.  
  257.             tRect.bottom = (tRect.top = gLine) + 1;
  258.  
  259.             PaintRect(&tRect);
  260.         }
  261.         else
  262.         {
  263.             SInt16 dataWidth = kVisualNumSpectrumEntries;
  264.             SInt16 halfWidth = dataWidth / 2;
  265.             SInt16 screenWidth = (srcRect.right - srcRect.left);
  266.             SInt16 minData = visualPluginData->minLevel[0];
  267.             SInt16 maxData = visualPluginData->maxLevel[0];
  268.             RGBColor tRGBColor;
  269.             SInt16 col,fraction = 0,index = 0;
  270.  
  271.             if (minData < visualPluginData->min)
  272.                 visualPluginData->min = minData;
  273.             else if (minData > visualPluginData->min)
  274.                 minData = visualPluginData->min++;
  275.  
  276.             if (maxData > visualPluginData->max)
  277.                 visualPluginData->max = maxData;
  278.             else if (maxData < visualPluginData->max)
  279.                 maxData = visualPluginData->max;
  280.  
  281.             if (dataWidth > screenWidth)
  282.             {
  283.                 for (col = srcRect.left;col < srcRect.right;col++)
  284.                 {
  285.                     SInt16 count = 0;
  286.                     SInt16 total = 0;
  287.  
  288.                     while (fraction < dataWidth)
  289.                     {
  290.                         if (index <= halfWidth)
  291.                             total += visualPluginData->renderData.spectrumData[0][index];
  292.                         else
  293.                             total += visualPluginData->renderData.spectrumData[1][dataWidth - index];
  294.  
  295.                         index++;
  296.                         fraction += screenWidth;
  297.                         count++;
  298.                     }
  299.                     fraction -= dataWidth;    // fix overflow
  300.                     total /= count;                    
  301.  
  302.                     total = (total - minData) * 255 / (maxData - minData);
  303.                     UInt8ToColorRGB(total,&tRGBColor);
  304.  
  305.                     SET_PIXEL(pixMapHdl,col,gLine,&tRGBColor);
  306.                 }
  307.             }
  308.             else    // screenWidth > dataWidth
  309.             {
  310.                 fraction = screenWidth - dataWidth;    // force overflow the first time
  311.  
  312.                 for (col = srcRect.left;col < srcRect.right;col++)
  313.                 {
  314.                     fraction += dataWidth;
  315.                     if (fraction >= screenWidth)    // overflow
  316.                     {
  317.                         SInt16 level;
  318.  
  319.                         fraction -= screenWidth;    // fix overflow
  320.  
  321.                         if (index <= halfWidth)
  322.                             level = visualPluginData->renderData.spectrumData[0][index];
  323.                         else
  324.                             level = visualPluginData->renderData.spectrumData[1][dataWidth - index];
  325.  
  326.                         index++;
  327.                         level = (level - minData) * 255 / (maxData - minData);
  328.                         UInt8ToColorRGB(level,&tRGBColor);
  329.                     }
  330.  
  331.                     SET_PIXEL(pixMapHdl,col,gLine,&tRGBColor);
  332.                 }
  333.             }
  334.         }
  335.     }
  336. }
  337.  
  338. static void _Filter(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect,Boolean onlyUpdate)
  339. {
  340.     BitMap*        srcBitMap;
  341.     BitMap*        dstBitMap;
  342.     Rect        srcRect = *destRect;
  343.     Rect        dstRect = srcRect;
  344.  
  345.     #pragma unused(onlyUpdate);
  346.  
  347.     if ((destPort == nil) || (visualPluginData->offscreen == nil))
  348.         return;
  349.  
  350.     OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
  351.  
  352.     srcBitMap    = GetPortCopyBitsBitMap(visualPluginData->offscreen);
  353.     dstBitMap    = GetPortCopyBitsBitMap(destPort);
  354.  
  355.     SetGWorld(destPort,nil);
  356.  
  357.     ForeColor(blackColor);
  358.     BackColor(whiteColor);
  359.  
  360.     srcRect.bottom = (srcRect.top += gLine) + 1;
  361.     dstRect.bottom = (dstRect.top += gLine) + 1;
  362.  
  363.     CopyBits(srcBitMap,dstBitMap,&srcRect,&dstRect,srcCopy,nil);
  364.  
  365.     SetGWorld(gSavePort,gSaveDevice);
  366. }
  367.  
  368. /*
  369.     RenderVisualPort
  370. */
  371.  
  372. extern "C" {
  373.  
  374. static void RenderVisualPort(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect,Boolean onlyUpdate)
  375. {
  376.         BitMap*        srcBitMap;
  377.     BitMap*        dstBitMap;
  378.     Rect        srcRect = *destRect;
  379.     Rect        dstRect = srcRect;
  380.     
  381.         GetGWorld(&gSavePort,&gSaveDevice);
  382.  
  383.  
  384.  
  385.     if ((nil == destPort) || (nil == destRect) ||
  386.         (nil == visualPluginData->offscreen))
  387.         return;
  388.         
  389.     OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
  390.         srcBitMap    = GetPortCopyBitsBitMap(visualPluginData->offscreen);
  391.     dstBitMap    = GetPortCopyBitsBitMap(destPort);
  392.  
  393.         Point mypoint = { 0 , 0};
  394.         PixMapHandle    pix = GetGWorldPixMap(visualPluginData->offscreen);
  395.  
  396.         LockPixels(pix);
  397.         visualPluginData->myfractal->DrawMe (mypoint ,(float)visualPluginData->renderData.spectrumData[1][0]);
  398.     UnlockPixels(pix);
  399.         
  400.         OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
  401.     SetGWorld(destPort,nil);
  402.  
  403.     ForeColor(blackColor);
  404.     BackColor(whiteColor);
  405.  
  406.     ::CopyBits( srcBitMap, dstBitMap, &srcRect, &dstRect, srcCopy, nil);
  407.  
  408.     SetGWorld(gSavePort,gSaveDevice);
  409.  
  410.  
  411.    
  412. //      ::CopyBits((BitMap *) *(GetPortPixMap(visualPluginData->offscreen)), GetPortBitMapForCopyBits(destPort),destRect, destRect, srcCopy, nil);
  413.  
  414.     //_Erase(visualPluginData,destPort,destRect,onlyUpdate);
  415.     //_Draw(visualPluginData,destPort,destRect,onlyUpdate);
  416.     _Filter(visualPluginData,destPort,destRect,onlyUpdate);
  417. }
  418. }
  419.  
  420. /*
  421.     AllocateVisualData is where you should allocate any information that depends
  422.     on the port or rect changing (like offscreen GWorlds).
  423. */
  424. static OSStatus AllocateVisualData(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect)
  425. {
  426.     OSStatus        status;
  427.     Rect            allocateRect;
  428.  
  429.     (void) destPort;
  430.  
  431.     GetGWorld(&gSavePort,&gSaveDevice);
  432.     
  433.     allocateRect = *destRect;
  434.     OffsetRect(&allocateRect,-allocateRect.left,-allocateRect.top);
  435.                 
  436.     status = NewGWorld(&visualPluginData->offscreen,32,&allocateRect,nil,nil,useTempMem);
  437.         
  438.     //    myfractal->ResetMe ();
  439.     
  440.     if (status == noErr)
  441.     {
  442.         PixMapHandle    pix = GetGWorldPixMap(visualPluginData->offscreen);
  443.  
  444.         LockPixels(pix);
  445.                 
  446.                 if (visualPluginData->myfractal != NULL) {
  447.                     delete visualPluginData->myfractal;
  448.  
  449.                 }
  450.                 
  451.                 visualPluginData->myfractal = (TDeepFractal*) new TDeepFractal();
  452.              //   InsetRect (&allocateRect, 6 , 6 );
  453.                // SetRect ( &allocateRect, 0,0,256,64);
  454.                 visualPluginData->myfractal->SetData (visualPluginData->offscreen, allocateRect.left, allocateRect.top, allocateRect.right, allocateRect.bottom);
  455.                 visualPluginData->myfractal->ResetMe();
  456.               //  InsetRect (&allocateRect, -6 , -6 );
  457.         // Offscreen starts out black
  458.         //SetGWorld(visualPluginData->offscreen,nil);
  459.         ForeColor(blackColor);
  460.         PaintRect(&allocateRect);
  461.                 UnlockPixels(pix);
  462.     }
  463.  
  464.     SetGWorld(gSavePort,gSaveDevice);
  465.     
  466.     return status;
  467. }
  468.  
  469. /*
  470.     DeallocateVisualData is where you should deallocate the .
  471. */
  472. static void DeallocateVisualData(VisualPluginData *visualPluginData)
  473. {
  474.     if (visualPluginData->offscreen != nil)
  475.     {
  476.         DisposeGWorld(visualPluginData->offscreen);
  477.         visualPluginData->offscreen = nil;
  478.     }
  479. }
  480.  
  481. // ChangeVisualPort
  482. //
  483. static OSStatus ChangeVisualPort(VisualPluginData *visualPluginData,CGrafPtr destPort,const Rect *destRect)
  484. {
  485.     OSStatus        status;
  486.     Boolean            doAllocate;
  487.     Boolean            doDeallocate;
  488.     
  489.     status = noErr;
  490.     
  491.     doAllocate        = false;
  492.     doDeallocate    = false;
  493.         
  494.     if (destPort != nil)
  495.     {
  496.         if (visualPluginData->destPort != nil)
  497.         {
  498.             if (false == EqualRect(destRect,&visualPluginData->destRect))
  499.             {
  500.                 doDeallocate    = true;
  501.                 doAllocate        = true;
  502.             }
  503.         }
  504.         else
  505.         {
  506.             doAllocate = true;
  507.         }
  508.     }
  509.     else
  510.     {
  511.         doDeallocate = true;
  512.     }
  513.     
  514.     if (doDeallocate)
  515.         DeallocateVisualData(visualPluginData);
  516.     
  517.     if (doAllocate)
  518.         status = AllocateVisualData(visualPluginData,destPort,destRect);
  519.  
  520.     if (status != noErr)
  521.         destPort = nil;
  522.  
  523.     visualPluginData->destPort = destPort;
  524.     if (destRect != nil)
  525.         visualPluginData->destRect = *destRect;
  526.  
  527.     return status;
  528. }
  529.  
  530. /*
  531.     ResetRenderData
  532. */
  533. static void ResetRenderData(VisualPluginData *visualPluginData)
  534. {
  535.     MemClear(&visualPluginData->renderData,sizeof(visualPluginData->renderData));
  536.  
  537.     visualPluginData->minLevel[0] = 
  538.         visualPluginData->minLevel[1] =
  539.         visualPluginData->maxLevel[0] =
  540.         visualPluginData->maxLevel[1] = 0;
  541. }
  542.  
  543. /* 
  544.     settingsControlHandler
  545. */
  546. pascal OSStatus settingsControlHandler(EventHandlerCallRef inRef,EventRef inEvent, void* userData)
  547. {
  548.     WindowRef wind=NULL;
  549.     ControlID controlID;
  550.     ControlRef control=NULL;
  551.     //get control hit by event
  552.     GetEventParameter(inEvent,kEventParamDirectObject,typeControlRef,NULL,sizeof(ControlRef),NULL,&control);
  553.     wind=GetControlOwner(control);
  554.     GetControlID(control,&controlID);
  555.     switch(controlID.id){
  556.         case kColorSettingID:
  557.                 gColorFlag=GetControlValue(control);
  558.                 break;
  559.         case kFlashSettingID:
  560.                 gFlashFlag=GetControlValue(control);
  561.                 break;
  562.         case kOKSettingID:
  563.                 HideWindow(wind);
  564.                 break;
  565.     }
  566.     return noErr;
  567. }
  568. /*
  569.     VisualPluginHandler
  570. */
  571. static OSStatus VisualPluginHandler(OSType message,VisualPluginMessageInfo *messageInfo,void *refCon)
  572. {
  573.     OSStatus            status;
  574.     VisualPluginData *    visualPluginData;
  575.  
  576.     visualPluginData = (VisualPluginData*) refCon;
  577.     
  578.     status = noErr;
  579.  
  580.     switch (message)
  581.     {
  582.         /*
  583.             Sent when the visual plugin is registered.  The plugin should do minimal
  584.             memory allocations here.  The resource fork of the plugin is still available.
  585.         */        
  586.         case kVisualPluginInitMessage:
  587.         {
  588.             visualPluginData = (VisualPluginData*) NewPtrClear(sizeof(VisualPluginData));
  589.             if (visualPluginData == nil)
  590.             {
  591.                 status = memFullErr;
  592.                 break;
  593.             }
  594.  
  595.             visualPluginData->appCookie    = messageInfo->u.initMessage.appCookie;
  596.             visualPluginData->appProc    = messageInfo->u.initMessage.appProc;
  597.  
  598.             /* Remember the file spec of our plugin file. We need this so we can open our resource fork during */
  599.             /* the configuration message */
  600.             
  601.             status = PlayerGetPluginFileSpec(visualPluginData->appCookie,visualPluginData->appProc,&visualPluginData->pluginFileSpec);
  602.  
  603.             messageInfo->u.initMessage.refCon    = (void*) visualPluginData;
  604.             break;
  605.         }
  606.             
  607.         /*
  608.             Sent when the visual plugin is unloaded
  609.         */        
  610.         case kVisualPluginCleanupMessage:
  611.             if (visualPluginData != nil)
  612.                 DisposePtr((Ptr)visualPluginData);
  613.             break;
  614.             
  615.         /*
  616.             Sent when the visual plugin is enabled.  iTunes currently enables all
  617.             loaded visual plugins.  The plugin should not do anything here.
  618.         */
  619.         case kVisualPluginEnableMessage:
  620.         case kVisualPluginDisableMessage:
  621.             break;
  622.  
  623.         /*
  624.             Sent if the plugin requests idle messages.  Do this by setting the kVisualWantsIdleMessages
  625.             option in the RegisterVisualMessage.options field.
  626.         */
  627.         case kVisualPluginIdleMessage:
  628.             if (false == visualPluginData->playing)
  629.                 RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,false);
  630.             break;
  631.                     
  632.         /*
  633.             Sent if the plugin requests the ability for the user to configure it.  Do this by setting
  634.             the kVisualWantsConfigure option in the RegisterVisualMessage.options field.
  635.         */
  636.         case kVisualPluginConfigureMessage:
  637.                        {
  638.                             static EventTypeSpec controlEvent={kEventClassControl,kEventControlHit};
  639.                             static const ControlID kColorSettingControlID={'cbox',kColorSettingID};
  640.                             static const ControlID kFlashSettingControlID={'cbox',kFlashSettingID};
  641.                             
  642.                             static WindowRef settingsDialog=NULL;
  643.                             static ControlRef color=NULL;
  644.                             static ControlRef flash=NULL;
  645.                             if(settingsDialog==NULL){
  646.                                 IBNibRef         nibRef;
  647.                                 //we have to find our bundle to load the nib inside of it
  648.                                 CFBundleRef iTunesXPlugin=CFBundleGetBundleWithIdentifier(CFSTR("iTunesXPlugin"));
  649.                                 CreateNibReferenceWithCFBundle(iTunesXPlugin,CFSTR("SettingsDialog"), &nibRef);
  650.                                 CreateWindowFromNib(nibRef, CFSTR("PluginSettings"), &settingsDialog);
  651.                                 DisposeNibReference(nibRef);
  652.                                 InstallWindowEventHandler(settingsDialog,NewEventHandlerUPP(settingsControlHandler),
  653.                                                     1,&controlEvent,0,NULL);
  654.                                 GetControlByID(settingsDialog,&kColorSettingControlID,&color);
  655.                                 GetControlByID(settingsDialog,&kFlashSettingControlID,&flash);
  656.                             }
  657.                             SetControlValue(color,gColorFlag);
  658.                             SetControlValue(flash,gFlashFlag);
  659.                             ShowWindow(settingsDialog);
  660.                         }break;
  661.         /*
  662.             Sent when iTunes is going to show the visual plugin in a port.  At
  663.             this point,the plugin should allocate any large buffers it needs.
  664.         */
  665.         case kVisualPluginShowWindowMessage:
  666.             visualPluginData->destOptions = messageInfo->u.showWindowMessage.options;
  667.  
  668.             status = ChangeVisualPort(    visualPluginData,
  669.                                         messageInfo->u.showWindowMessage.port,
  670.                                         &messageInfo->u.showWindowMessage.drawRect);
  671.             if (status == noErr)
  672.                 RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,true);
  673.             break;
  674.             
  675.         /*
  676.             Sent when iTunes is no longer displayed.
  677.         */
  678.         case kVisualPluginHideWindowMessage:
  679.             (void) ChangeVisualPort(visualPluginData,nil,nil);
  680.  
  681.             MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  682.             MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  683.             break;
  684.         
  685.         /*
  686.             Sent when iTunes needs to change the port or rectangle of the currently
  687.             displayed visual.
  688.         */
  689.         case kVisualPluginSetWindowMessage:
  690.             visualPluginData->destOptions = messageInfo->u.setWindowMessage.options;
  691.  
  692.             status = ChangeVisualPort(    visualPluginData,
  693.                                         messageInfo->u.setWindowMessage.port,
  694.                                         &messageInfo->u.setWindowMessage.drawRect);
  695.  
  696.             if (status == noErr)
  697.                 RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,true);
  698.             break;
  699.         
  700.         /*
  701.             Sent for the visual plugin to render a frame.
  702.         */
  703.         case kVisualPluginRenderMessage:
  704.             visualPluginData->renderTimeStampID    = messageInfo->u.renderMessage.timeStampID;
  705.  
  706.             //ProcessRenderData(visualPluginData,messageInfo->u.renderMessage.renderData);
  707.                 
  708.             RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,false);
  709.             break;
  710. #if 0            
  711.         /*
  712.             Sent for the visual plugin to render directly into a port.  Not necessary for normal
  713.             visual plugins.
  714.         */
  715.         case kVisualPluginRenderToPortMessage:
  716.             status = unimpErr;
  717.             break;
  718. #endif 0
  719.         /*
  720.             Sent in response to an update event.  The visual plugin should update
  721.             into its remembered port.  This will only be sent if the plugin has been
  722.             previously given a ShowWindow message.
  723.         */    
  724.         case kVisualPluginUpdateMessage:
  725.             RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,true);
  726.             break;
  727.         
  728.         /*
  729.             Sent when the player starts.
  730.         */
  731.         case kVisualPluginPlayMessage:
  732.             if (messageInfo->u.playMessage.trackInfo != nil)
  733.                 visualPluginData->trackInfo = *messageInfo->u.playMessage.trackInfo;
  734.             else
  735.                 MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  736.  
  737.             if (messageInfo->u.playMessage.streamInfo != nil)
  738.                 visualPluginData->streamInfo = *messageInfo->u.playMessage.streamInfo;
  739.             else
  740.                 MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  741.         
  742.             visualPluginData->playing = true;
  743.             break;
  744.  
  745.         /*
  746.             Sent when the player changes the current track information.  This
  747.             is used when the information about a track changes,or when the CD
  748.             moves onto the next track.  The visual plugin should update any displayed
  749.             information about the currently playing song.
  750.         */
  751.         case kVisualPluginChangeTrackMessage:
  752.             if (messageInfo->u.changeTrackMessage.trackInfo != nil)
  753.                 visualPluginData->trackInfo = *messageInfo->u.changeTrackMessage.trackInfo;
  754.             else
  755.                 MemClear(&visualPluginData->trackInfo,sizeof(visualPluginData->trackInfo));
  756.  
  757.             if (messageInfo->u.changeTrackMessage.streamInfo != nil)
  758.                 visualPluginData->streamInfo = *messageInfo->u.changeTrackMessage.streamInfo;
  759.             else
  760.                 MemClear(&visualPluginData->streamInfo,sizeof(visualPluginData->streamInfo));
  761.             break;
  762.  
  763.         /*
  764.             Sent when the player stops.
  765.         */
  766.         case kVisualPluginStopMessage:
  767.             visualPluginData->playing = false;
  768.             
  769.             ResetRenderData(visualPluginData);
  770.  
  771.             RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,true);
  772.             break;
  773.         
  774.         /*
  775.             Sent when the player changes position.
  776.         */
  777.         case kVisualPluginSetPositionMessage:
  778.             break;
  779.  
  780.         /*
  781.             Sent when the player pauses.  iTunes does not currently use pause or unpause.
  782.             A pause in iTunes is handled by stopping and remembering the position.
  783.         */
  784.         case kVisualPluginPauseMessage:
  785.             visualPluginData->playing = false;
  786.  
  787.             ResetRenderData(visualPluginData);
  788.  
  789.             RenderVisualPort(visualPluginData,visualPluginData->destPort,&visualPluginData->destRect,true);
  790.             break;
  791.             
  792.         /*
  793.             Sent when the player unpauses.  iTunes does not currently use pause or unpause.
  794.             A pause in iTunes is handled by stopping and remembering the position.
  795.         */
  796.         case kVisualPluginUnpauseMessage:
  797.             visualPluginData->playing = true;
  798.             break;
  799.         
  800.         /*
  801.             Sent to the plugin in response to a MacOS event.  The plugin should return noErr
  802.             for any event it handles completely,or an error (unimpErr) if iTunes should handle it.
  803.         */
  804.         case kVisualPluginEventMessage:
  805.             {
  806.                 EventRecord* tEventPtr = messageInfo->u.eventMessage.event;
  807.                 if ((tEventPtr->what == keyDown) || (tEventPtr->what == autoKey))
  808.                 {    // charCodeMask,keyCodeMask;
  809.                     char theChar = tEventPtr->message & charCodeMask;
  810.  
  811.                     switch (theChar)
  812.                     {
  813.                     case    'c':
  814.                     case    'C':
  815.                                                 visualPluginData->myfractal->ResetMe ();
  816.                         gColorFlag = !gColorFlag;
  817.                         status = noErr;
  818.                         break;
  819.                     case    'f':
  820.                     case    'F':
  821.                         gFlashFlag = !gFlashFlag;
  822.                         status = noErr;
  823.                         break;
  824.                     default:
  825.                         status = unimpErr;
  826.                         break;
  827.                     }
  828.                 }
  829.                 else
  830.                     status = unimpErr;
  831.             }
  832.             break;
  833.  
  834.         default:
  835.             status = unimpErr;
  836.             break;
  837.     }
  838.     return status;    
  839. }
  840.  
  841. /*
  842.     RegisterVisualPlugin
  843. */
  844. static OSStatus RegisterVisualPlugin(PluginMessageInfo *messageInfo)
  845. {
  846.     OSStatus            status;
  847.     PlayerMessageInfo    playerMessageInfo;
  848.     Str255                pluginName = kTVisualPluginName;
  849.         
  850.     MemClear(&playerMessageInfo.u.registerVisualPluginMessage,sizeof(playerMessageInfo.u.registerVisualPluginMessage));
  851.     
  852.     BlockMoveData((Ptr)&pluginName[0],(Ptr)&playerMessageInfo.u.registerVisualPluginMessage.name[0],pluginName[0] + 1);
  853.  
  854.     SetNumVersion(&playerMessageInfo.u.registerVisualPluginMessage.pluginVersion,kTVisualPluginMajorVersion,kTVisualPluginMinorVersion,kTVisualPluginReleaseStage,kTVisualPluginNonFinalRelease);
  855.  
  856.     playerMessageInfo.u.registerVisualPluginMessage.options                    = kVisualWantsIdleMessages | kVisualWantsConfigure;
  857.     playerMessageInfo.u.registerVisualPluginMessage.handler                    = (VisualPluginProcPtr)VisualPluginHandler;
  858.     playerMessageInfo.u.registerVisualPluginMessage.registerRefCon            = 0;
  859.     playerMessageInfo.u.registerVisualPluginMessage.creator                    = kTVisualPluginCreator;
  860.     
  861.     playerMessageInfo.u.registerVisualPluginMessage.timeBetweenDataInMS        = 0xFFFFFFFF; // 16 milliseconds = 1 Tick,0xFFFFFFFF = Often as possible.
  862.     playerMessageInfo.u.registerVisualPluginMessage.numWaveformChannels        = 2;
  863.     playerMessageInfo.u.registerVisualPluginMessage.numSpectrumChannels        = 2;
  864.     
  865.     playerMessageInfo.u.registerVisualPluginMessage.minWidth                = 64;
  866.     playerMessageInfo.u.registerVisualPluginMessage.minHeight                = 64;
  867.     playerMessageInfo.u.registerVisualPluginMessage.maxWidth                = 32767;
  868.     playerMessageInfo.u.registerVisualPluginMessage.maxHeight                = 32767;
  869.     playerMessageInfo.u.registerVisualPluginMessage.minFullScreenBitDepth    = 0;
  870.     playerMessageInfo.u.registerVisualPluginMessage.maxFullScreenBitDepth    = 0;
  871.     playerMessageInfo.u.registerVisualPluginMessage.windowAlignmentInBytes    = 0;
  872.     
  873.     status = PlayerRegisterVisualPlugin(messageInfo->u.initMessage.appCookie,messageInfo->u.initMessage.appProc,&playerMessageInfo);
  874.         
  875.     return status;
  876.     
  877. }
  878.  
  879. /**\
  880. |**|    main entrypoint
  881. \**/
  882. extern "C" {
  883. extern OSStatus iTunesPluginMainMachO(OSType message,PluginMessageInfo *messageInfo,void *refCon)
  884. {
  885.     OSStatus        status;
  886.     
  887.     (void) refCon;
  888.     
  889.     switch (message)
  890.     {
  891.         case kPluginInitMessage:
  892.             status = RegisterVisualPlugin(messageInfo);
  893.             break;
  894.             
  895.         case kPluginCleanupMessage:
  896.             status = noErr;
  897.             break;
  898.             
  899.         default:
  900.             status = unimpErr;
  901.             break;
  902.     }
  903.     
  904.     return status;
  905. }
  906. }