home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Sample Code / Video Digitizer / Hack TV / HackTV.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-06  |  25.0 KB  |  1,010 lines  |  [TEXT/MPS ]

  1. /*
  2.   File:            HackTV.c
  3.   Contains:        Hack TV Routines.
  4.   Written by:    Gary Woodcock / QT Engineering
  5.   Copyright:    © 1992-1994 by Apple Computer, Inc., all rights reserved.
  6.   Change History (most recent first):
  7.   <1>         12/4/94        khs        changed the format of the file to the new look and feel
  8.   To Do:
  9. */
  10.  
  11.  
  12. // INCLUDES
  13. #include <Menus.h>
  14. #include <Windows.h>
  15. #include <QuickDraw.h>
  16. #include <OSEvents.h>
  17. #include <Resources.h>
  18. #include <Desk.h>
  19. #include <Fonts.h>
  20. #include <ToolUtils.h>
  21. #include <Scrap.h>
  22. #include <Printing.h>
  23. #include <Errors.h>
  24. #include <SegLoad.h>
  25.  
  26. #include <QuickTimeComponents.h>
  27. #include <ImageCompression.h>
  28.  
  29. #ifndef THINK_C
  30. #include <Packages.h>
  31. #endif THINK_C
  32.  
  33.  
  34. // CONSTANTS
  35. // Menu bar
  36. enum
  37. {
  38.     kMenuBarID = 128
  39. };
  40.  
  41. // Menus
  42. enum
  43. {
  44.     kAppleID = 128, kFileID, kEditID, kMonitorID
  45. };
  46.  
  47. // Apple menu items
  48. enum
  49. {
  50.     kAboutItem = 1
  51. };
  52.  
  53. // File menu items
  54. enum
  55. {
  56.     kPageSetupItem = 1, kPrintItem, kQuitItem = 4
  57. };
  58.  
  59. // Edit menu items
  60. enum
  61. {
  62.     kUndoItem = 1, kCutItem = 3, kCopyItem, kPasteItem, kClearItem
  63. };
  64.  
  65. // Monitor menu items
  66. enum
  67. {
  68.     kVideoSettingsItem = 1, kSoundSettingsItem, kQuarterSizeItem = 4, kHalfSizeItem, kFullSizeItem
  69. };
  70.  
  71. // Dialog IDs
  72. enum
  73. {
  74.     kAboutDLOGID = 128, kMonitorDLOGID
  75. };
  76.  
  77. // Common DITL items
  78. enum
  79. {
  80.     kAboutOKButton = 1, kAboutOKButtonOutline
  81. };
  82.  
  83.  
  84. // GLOBALS
  85. MenuHandle gAppleMenu;
  86. MenuHandle gFileMenu;
  87. MenuHandle gEditMenu;
  88. MenuHandle gMonitorMenu;
  89. EventRecord gTheEvent;
  90. Boolean gQuitFlag;
  91. SeqGrabComponent gSeqGrabber;
  92. SGChannel gVideoChannel;
  93. SGChannel gSoundChannel;
  94. WindowPtr gMonitor;
  95. Rect gActiveVideoRect;
  96. PicHandle gMonitorPICT;
  97. Boolean gFullSize;
  98. Boolean gHalfSize;
  99. Boolean gQuarterSize;
  100. THPrint gPrintRec;
  101. ICMAlignmentProcRecordPtr gSeqGrabberAlignProc;
  102.  
  103.  
  104. // FUNCTION PROTOTYPES
  105. static void DoInit(void);
  106.  
  107. static void DoMenuSetup(void);
  108.  
  109. static void HandleEvent(void);
  110.  
  111. static void HandleMouseDown(void);
  112.  
  113. static void AdjustMenus(void);
  114.  
  115. static void Enable(Handle menu,
  116.                    short item,
  117.                    Boolean ok);
  118.  
  119. static void HandleMenu(long menu);
  120.  
  121. static void DoAboutDialog(void);
  122.  
  123. static void DoQuit(void);
  124.  
  125. pascal void AboutDrawProc(DialogPtr theDialog,
  126.                           short theItemNum);
  127.  
  128. static OSErr XorRectToRgn(Rect* srcRectA,
  129.                           Rect* srcRectB,
  130.                           RgnHandle* destRgn);
  131.  
  132. pascal Boolean SeqGrabberModalFilterProc(DialogPtr theDialog,
  133.                                          EventRecord* theEvent,
  134.                                          short* itemHit,
  135.                                          long refCon);
  136.  
  137.  
  138. // FUNCTIONS
  139. //-----------------------------------------------------------------------
  140.  
  141. void main(void)
  142. {
  143.     // Init
  144.     DoInit();
  145.     DoMenuSetup();
  146.  
  147.     // Eat events until done
  148.     do
  149.     {
  150.         HandleEvent();
  151.     } while (!gQuitFlag);
  152.  
  153.     // Take off, eh?
  154.     ExitToShell();
  155. }
  156.  
  157. //-----------------------------------------------------------------------
  158.  
  159. static void DoInit(void)
  160. {
  161.     ComponentDescription theDesc;
  162.     ComponentResult result = noErr;
  163.     Component sgCompID = 0L;
  164.     GrafPtr savedPort;
  165.  
  166.     // Set up quit flag
  167.     gQuitFlag = false;
  168.  
  169.     // MacMantra™
  170.     MaxApplZone();
  171.     InitGraf(&qd.thePort);
  172.     InitFonts();
  173.     FlushEvents(everyEvent, 0);
  174.     InitWindows();
  175.     InitMenus();
  176.     TEInit();
  177.     InitDialogs(0L);
  178.     InitCursor();
  179.     EnterMovies();
  180.     MoreMasters();
  181.     MoreMasters();
  182.     MoreMasters();
  183.     MoreMasters();
  184.  
  185.     // Init stuff
  186.     gSeqGrabber = 0L;
  187.     gVideoChannel = 0L;
  188.     gSoundChannel = 0L;
  189.     gMonitorPICT = nil;
  190.     gPrintRec = (THPrint)NewHandleClear(sizeof(TPrint));
  191.  
  192.     // Find and open a sequence grabber
  193.     theDesc.componentType = SeqGrabComponentType;
  194.     theDesc.componentSubType = 0L;
  195.     theDesc.componentManufacturer = 'appl';
  196.     theDesc.componentFlags = 0L;
  197.     theDesc.componentFlagsMask = 0L;
  198.     sgCompID = FindNextComponent(nil, &theDesc);
  199.     if (sgCompID != 0L)
  200.     {
  201.         gSeqGrabber = OpenComponent(sgCompID);
  202.     }
  203.  
  204.     // If we got a sequence grabber, set it up
  205.     if (gSeqGrabber != 0L)
  206.     {
  207.         // Get the monitor
  208.         gMonitor = GetNewDialog(kMonitorDLOGID, nil, (WindowPtr) - 1L);
  209.         if (gMonitor != nil)
  210.         {
  211.             // Initialize the sequence grabber
  212.             GetPort(&savedPort);
  213.             SetPort(gMonitor);
  214.             result = SGInitialize(gSeqGrabber);
  215.             if (result == noErr)
  216.             {
  217.                 result = SGSetGWorld(gSeqGrabber, (CGrafPtr)gMonitor, nil);
  218.  
  219.                 // Get a video channel
  220.                 result = SGNewChannel(gSeqGrabber, VideoMediaType, &gVideoChannel);
  221.                 if ((gVideoChannel != nil) && (result == noErr))
  222.                 {
  223.                     short width;
  224.                     short height;
  225.  
  226.                     gQuarterSize = true;
  227.                     gHalfSize = false;
  228.                     gFullSize = false;
  229.  
  230.                     result = SGGetSrcVideoBounds(gVideoChannel, &gActiveVideoRect);
  231.                     width = (gActiveVideoRect.right - gActiveVideoRect.left) / 4;
  232.                     height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 4;
  233.                     SizeWindow(gMonitor, width, height, false);
  234.                     ShowWindow(gMonitor);
  235.  
  236.                     result = SGSetChannelUsage(gVideoChannel, seqGrabPreview);
  237.                     result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect));
  238.                 }
  239.  
  240.                 // Get a sound channel
  241.                 result = SGNewChannel(gSeqGrabber, SoundMediaType, &gSoundChannel);
  242.                 if ((gSoundChannel != nil) && (result == noErr))
  243.                 {
  244.                     result = SGSetChannelUsage(gSoundChannel, seqGrabPreview);
  245.                 }
  246.  
  247.                 // Get ready…
  248.                 result = SGPrepare(gSeqGrabber, true, false);
  249.             }
  250.  
  251.             // Go!
  252.             result = SGStartPreview(gSeqGrabber);
  253.             SetPort(savedPort);
  254.         }
  255.     }
  256. }
  257.  
  258. //-----------------------------------------------------------------------
  259.  
  260. static void DoMenuSetup(void)
  261. {
  262.     Handle theMenuBar = GetNewMBar(kMenuBarID);
  263.  
  264.     // Set up our menus
  265.     SetMenuBar(theMenuBar);
  266.     gAppleMenu = GetMHandle(kAppleID);
  267.     gFileMenu = GetMHandle(kFileID);
  268.     gEditMenu = GetMHandle(kEditID);
  269.     gMonitorMenu = GetMHandle(kMonitorID);
  270.     AddResMenu(gAppleMenu, 'DRVR');
  271.  
  272.     // Last minute adjustments…
  273.     AdjustMenus();
  274. }
  275.  
  276. //-----------------------------------------------------------------------
  277.  
  278. static void HandleEvent(void)
  279. {
  280.     ComponentResult result = noErr;
  281.  
  282.     // Do system stuff
  283.     HiliteMenu(0);
  284.     SystemTask();
  285.  
  286.     // Give some time to the sequence grabber
  287.     if (gSeqGrabber != 0L)
  288.         result = SGIdle(gSeqGrabber);
  289.  
  290.     // Suck an event
  291.     if (WaitNextEvent(everyEvent, &gTheEvent, 0, 0))
  292.     {
  293.         // What was it?
  294.         switch (gTheEvent.what)
  295.         {
  296.             case mouseDown:
  297.                 {
  298.                     // Handle it
  299.                     HandleMouseDown();
  300.                     break;
  301.                 }
  302.             case keyDown:
  303.             case autoKey:
  304.                 {
  305.                     char theChar = gTheEvent.message & charCodeMask;
  306.                     long theMenu = MenuKey(theChar);
  307.  
  308.                     // Handle menu command keys
  309.                     HandleMenu(theMenu);
  310.                     break;
  311.                 }
  312.             case updateEvt:
  313.                 {
  314.                     if ((gMonitor != nil) && ((WindowPtr)(gTheEvent.message) == (WindowPtr)gMonitor))
  315.                     {
  316.                         // Eat the update
  317.                         BeginUpdate(gMonitor);
  318.                         EndUpdate(gMonitor);
  319.                     }
  320.                     break;
  321.                 }
  322.             default:                            // We don't really care about any other events, but you might, so feel free
  323.                 {
  324.                     break;
  325.                 }
  326.         }
  327.     }
  328. }
  329.  
  330. //-----------------------------------------------------------------------
  331.  
  332. static void HandleMouseDown(void)
  333. {
  334.     WindowPtr theWindow;
  335.     short windowCode = FindWindow(gTheEvent.where, &theWindow);
  336.  
  337.     // Where was the mouse down?
  338.     switch (windowCode)
  339.     {
  340.         case inSysWindow:
  341.             {
  342.                 SystemClick(&gTheEvent, theWindow);
  343.                 break;
  344.             }
  345.         case inMenuBar:
  346.             {
  347.                 AdjustMenus();
  348.                 HandleMenu(0L);
  349.                 break;
  350.             }
  351.         case inDrag:
  352.             {
  353.                 // Was it the monitor?
  354.                 if (theWindow == gMonitor)
  355.                 {
  356.                     ComponentResult result = noErr;
  357.                     Rect limitRect;
  358.                     RgnHandle grayRgn = GetGrayRgn();
  359.                     Rect boundsRect;
  360.  
  361.                     // Find bounds
  362.                     if (grayRgn != nil)
  363.                     {
  364.                         limitRect = (*grayRgn)->rgnBBox;
  365.                     }
  366.                     else
  367.                     {
  368.                         limitRect = qd.screenBits.bounds;
  369.                     }
  370.  
  371.                     // Pause the sequence grabber
  372.                     result = SGPause(gSeqGrabber, true);
  373.  
  374.                     if (gVideoChannel != nil)
  375.                     {
  376.                         // Get the alignment proc
  377.                         result = SGGetAlignmentProc(gSeqGrabber, gSeqGrabberAlignProc);
  378.  
  379.                         // Drag it with the totally cool DragAlignedWindow
  380.                         // Note that the sequence grabber can get real confused when you use this
  381.                         // call if you've got multiple video channels - this'll get fixed in the 
  382.                         // next release.  
  383.                         result = SGGetChannelBounds(gVideoChannel, &boundsRect);
  384.                         DragAlignedWindow(theWindow, gTheEvent.where, &limitRect, &boundsRect, gSeqGrabberAlignProc);
  385.                     }
  386.                     else
  387.                     {
  388.                         DragWindow(theWindow, gTheEvent.where, &limitRect);
  389.                     }
  390.  
  391.                     // Start up the sequence grabber
  392.                     result = SGPause(gSeqGrabber, false);
  393.                 }
  394.                 break;
  395.             }
  396.         default:
  397.             {
  398.                 break;
  399.             }
  400.     }
  401. }
  402.  
  403. //-----------------------------------------------------------------------
  404.  
  405. static void AdjustMenus(void)
  406. {
  407.     register WindowPeek wp = nil;
  408.     short kind = 0;
  409.     Boolean DA = false;
  410.     ComponentResult result = noErr;
  411.  
  412.     // What kind of window is frontmost?
  413.     wp = (WindowPeek)FrontWindow();
  414.     kind = wp ? wp->windowKind : 0;
  415.     DA = kind < 0;
  416.  
  417.     // Set our menu item states appropriately
  418.  
  419.     // Apple menu
  420.     Enable((Handle)gAppleMenu, kAboutItem, true);
  421.  
  422.     // File menu
  423.     Enable((Handle)gFileMenu, kPageSetupItem, true);
  424.     Enable((Handle)gFileMenu, kPrintItem, (gVideoChannel != 0L ? true : false));
  425.     Enable((Handle)gFileMenu, kQuitItem, true);
  426.  
  427.     // Edit menu
  428.     Enable((Handle)gEditMenu, kUndoItem, DA);
  429.     Enable((Handle)gEditMenu, kCutItem, DA || (gVideoChannel != 0L));
  430.     Enable((Handle)gEditMenu, kCopyItem, DA || (gVideoChannel != 0L));
  431.     Enable((Handle)gEditMenu, kPasteItem, DA);
  432.     Enable((Handle)gEditMenu, kClearItem, DA);
  433.  
  434.     // Monitor menu
  435.     Enable((Handle)gMonitorMenu, kVideoSettingsItem, (gVideoChannel != 0L ? true : false));
  436.     Enable((Handle)gMonitorMenu, kSoundSettingsItem, (gSoundChannel != 0L ? true : false));
  437.     Enable((Handle)gMonitorMenu, kQuarterSizeItem, (gVideoChannel != 0L ? true : false));
  438.     CheckItem(gMonitorMenu, kQuarterSizeItem, gQuarterSize);
  439.     Enable((Handle)gMonitorMenu, kHalfSizeItem, (gVideoChannel != 0L ? true : false));
  440.     CheckItem(gMonitorMenu, kHalfSizeItem, gHalfSize);
  441.     Enable((Handle)gMonitorMenu, kFullSizeItem, (gVideoChannel != 0L ? true : false));
  442.     CheckItem(gMonitorMenu, kFullSizeItem, gFullSize);
  443.  
  444.     // Draw it
  445.     DrawMenuBar();
  446. }
  447.  
  448. //-----------------------------------------------------------------------
  449.  
  450. static void Enable(Handle menu,
  451.                    short item,
  452.                    Boolean ok)
  453. {
  454.     // Utility routine to enable and disable menu items
  455.     if (ok)
  456.     {
  457.         EnableItem((MenuHandle)menu, item);
  458.     }
  459.     else
  460.     {
  461.         DisableItem((MenuHandle)menu, item);
  462.     }
  463. }
  464.  
  465. //-----------------------------------------------------------------------
  466.  
  467. static void HandleMenu(long theMenu)
  468. {
  469.     long mSelect;
  470.     short menuID;
  471.     short menuItem;
  472.     ComponentResult result = noErr;
  473.  
  474.     // Did we get a menu?
  475.     if (theMenu == 0L)
  476.     {
  477.         // Nope, get it from menu select
  478.         mSelect = MenuSelect(gTheEvent.where);
  479.     }
  480.     else
  481.     {
  482.         // Yep, use it
  483.         mSelect = theMenu;
  484.     }
  485.  
  486.     // Decode it
  487.     menuID = HiWord(mSelect);
  488.     menuItem = LoWord(mSelect);
  489.  
  490.     // Which menu is it?
  491.     switch (menuID)
  492.     {
  493.         case kAppleID:
  494.             {
  495.                 if (menuItem == kAboutItem)
  496.                 {
  497.                     // Do the boring about box
  498.                     DoAboutDialog();
  499.                 }
  500.                 else                            // It's a DA
  501.                     {
  502.                         Str255 name;
  503.                         GrafPtr savedPort;
  504.  
  505.                         // Open the DA
  506.                         GetPort(&savedPort);
  507.                         GetItem(gAppleMenu, menuItem, name);
  508.                         OpenDeskAcc(name);
  509.                         SetPort(savedPort);
  510.                     }
  511.                 break;
  512.             }
  513.         case kFileID:
  514.             {
  515.                 switch (menuItem)
  516.                 {
  517.                     case kPageSetupItem:
  518.                         {
  519.                             // Do the page setup dialog
  520.                             PrOpen();
  521.                             PrStlDialog(gPrintRec);
  522.                             PrClose();
  523.                             break;
  524.                         }
  525.                     case kPrintItem:
  526.                         {
  527.                             TPPrPort printPort;
  528.                             TPrStatus printStatus;
  529.  
  530.                             // Copy a frame from the monitor
  531.                             if (gMonitorPICT != nil)
  532.                             {
  533.                                 KillPicture(gMonitorPICT);
  534.                             }
  535.                             gMonitorPICT = nil;
  536.                             result = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
  537.                             if ((result == noErr) && (gMonitorPICT != nil))
  538.                             {
  539.                                 // Print it
  540.                                 HLock((Handle)gMonitorPICT);
  541.                                 PrOpen();
  542.                                 if (PrJobDialog(gPrintRec))
  543.                                 {
  544.                                     printPort = PrOpenDoc(gPrintRec, nil, nil);
  545.                                     result = PrError();
  546.                                     PrOpenPage(printPort, 0);
  547.                                     result = PrError();
  548.                                     DrawPicture(gMonitorPICT, &((**gMonitorPICT).picFrame));
  549.                                     PrClosePage(printPort);
  550.                                     result = PrError();
  551.                                     PrCloseDoc(printPort);
  552.                                     result = PrError();
  553.                                     if ((**gPrintRec).prJob.bJDocLoop == bSpoolLoop)
  554.                                     {
  555.                                         PrPicFile(gPrintRec, 0, 0, 0, &printStatus);
  556.                                         result = PrError();
  557.                                     }
  558.                                 }
  559.                                 PrClose();
  560.                                 result = PrError();
  561.                                 HUnlock((Handle)gMonitorPICT);
  562.                             }
  563.                             break;
  564.                         }
  565.                     case kQuitItem:
  566.                         {
  567.                             // Let's scram
  568.                             DoQuit();
  569.                             break;
  570.                         }
  571.                 }
  572.                 break;
  573.             }
  574.         case kEditID:
  575.             {
  576.                 // Is this a DA kind of thing?
  577.                 if (!SystemEdit(menuItem - 1))
  578.                 {
  579.                     // We only do cut and copy
  580.                     if ((menuItem == kCutItem) || (menuItem == kCopyItem))
  581.                     {
  582.                         // Copy a frame from the monitor
  583.                         if (gMonitorPICT != nil)
  584.                         {
  585.                             KillPicture(gMonitorPICT);
  586.                         }
  587.                         gMonitorPICT = nil;
  588.                         result = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen);
  589.                         if ((result == noErr) && (gMonitorPICT != nil))
  590.                         {
  591.                             result = ZeroScrap();
  592.                             HLock((Handle)gMonitorPICT);
  593.                             result = PutScrap(GetHandleSize((Handle)gMonitorPICT), 'PICT', *(Handle)gMonitorPICT);
  594.                             HUnlock((Handle)gMonitorPICT);
  595.                             if (result != noErr)
  596.                             {
  597.                                 // Cut or copy failed, probably due to lack of memory
  598.                             }
  599.                         }
  600.                     }
  601.                 }
  602.                 break;
  603.             }
  604.         case kMonitorID:
  605.             {
  606.                 switch (menuItem)
  607.                 {
  608.                         short width;
  609.                         short height;
  610.                         Rect curBounds;
  611.                         Rect curVideoRect;
  612.                         Rect newVideoRect;
  613.                         Rect newBounds;
  614.                         Rect maxBoundsRect;
  615.                         GrafPtr savedPort;
  616.                         RgnHandle deadRgn;
  617.                         Rect boundsRect;
  618.  
  619.                     case kVideoSettingsItem:
  620.                         {
  621.                             if ((gSeqGrabber != 0L) && (gVideoChannel != 0L))
  622.                             {
  623.                                 Rect newActiveVideoRect;
  624.                                 Rect adjustedActiveVideoRect;
  625.  
  626.                                 // Get our current state
  627.                                 result = SGGetChannelBounds(gVideoChannel, &curBounds);
  628.                                 result = SGGetVideoRect(gVideoChannel, &curVideoRect);
  629.  
  630.                                 // Pause
  631.                                 result = SGPause(gSeqGrabber, true);
  632.  
  633.                                 // Do the dialog thang
  634.                                 result = SGSettingsDialog(gSeqGrabber, gVideoChannel, 0, nil, 0L, SeqGrabberModalFilterProc, (long)StripAddress((Ptr)gMonitor));
  635.  
  636.                                 // What happened?
  637.                                 result = SGGetVideoRect(gVideoChannel, &newVideoRect);
  638.                                 result = SGGetSrcVideoBounds(gVideoChannel, &newActiveVideoRect);
  639.  
  640.                                 // Set up our port
  641.                                 GetPort(&savedPort);
  642.                                 SetPort(gMonitor);
  643.  
  644.                                 // Has our active rect changed?
  645.                                 // If so, it's because our video standard changed (e.g., NTSC to PAL),
  646.                                 // and we need to adjust our monitor window
  647.                                 if (!EqualRect(&gActiveVideoRect, &newActiveVideoRect))
  648.                                 {
  649.                                     if (gFullSize)
  650.                                     {
  651.                                         width = newActiveVideoRect.right - newActiveVideoRect.left;
  652.                                         height = newActiveVideoRect.bottom - newActiveVideoRect.top;
  653.  
  654.                                         gActiveVideoRect = newActiveVideoRect;
  655.                                         SizeWindow(gMonitor, width, height, false);
  656.                                         result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect));
  657.                                     }
  658.                                     else if (gHalfSize)
  659.                                     {
  660.                                         width = (newActiveVideoRect.right - newActiveVideoRect.left) / 2;
  661.                                         height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 2;
  662.  
  663.                                         gActiveVideoRect = newActiveVideoRect;
  664.                                         SizeWindow(gMonitor, width, height, false);
  665.                                         result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect));
  666.                                     }
  667.                                     else if (gQuarterSize)
  668.                                     {
  669.                                         width = (newActiveVideoRect.right - newActiveVideoRect.left) / 4;
  670.                                         height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 4;
  671.  
  672.                                         gActiveVideoRect = newActiveVideoRect;
  673.                                         SizeWindow(gMonitor, width, height, false);
  674.                                         result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect));
  675.                                     }
  676.                                 }
  677.  
  678.                                 // Has our crop changed?
  679.                                 // This code shows how to be crop video panel friendly
  680.                                 // Two important things - 
  681.                                 // 1) Be aware that you might have been cropped and adjust your
  682.                                 //    video window appropriately
  683.                                 // 2) Be aware that you might have been adjusted and attempt to
  684.                                 //    account for this.  Adjusting refers to using the digitizer
  685.                                 //    rect to "adjust" the active source rect within the maximum
  686.                                 //    source rect.  This is useful if you're getting those nasty
  687.                                 //    black bands on the sides of your video display - you can use
  688.                                 //    the control-arrow key sequence to shift the active source 
  689.                                 //    rect around when you're in the crop video panel
  690.  
  691.                                 adjustedActiveVideoRect = gActiveVideoRect;
  692.                                 if (!EqualRect(&curVideoRect, &newVideoRect))
  693.                                 {
  694.                                     if ((newVideoRect.left < gActiveVideoRect.left) || (newVideoRect.right > gActiveVideoRect.right) || (newVideoRect.top < gActiveVideoRect.top) || (newVideoRect.bottom > gActiveVideoRect.bottom))
  695.                                     {
  696.                                         if (newVideoRect.left < gActiveVideoRect.left)
  697.                                         {
  698.                                             adjustedActiveVideoRect.left = newVideoRect.left;
  699.                                             adjustedActiveVideoRect.right -= (gActiveVideoRect.left - newVideoRect.left);
  700.                                         }
  701.                                         if (newVideoRect.right > gActiveVideoRect.right)
  702.                                         {
  703.                                             adjustedActiveVideoRect.right = newVideoRect.right;
  704.                                             adjustedActiveVideoRect.left += (newVideoRect.right - gActiveVideoRect.right);
  705.                                         }
  706.                                         if (newVideoRect.top < gActiveVideoRect.top)
  707.                                         {
  708.                                             adjustedActiveVideoRect.top = newVideoRect.top;
  709.                                             adjustedActiveVideoRect.bottom -= (gActiveVideoRect.top - newVideoRect.top);
  710.                                         }
  711.                                         if (newVideoRect.bottom > gActiveVideoRect.bottom)
  712.                                         {
  713.                                             adjustedActiveVideoRect.bottom = newVideoRect.bottom;
  714.                                             adjustedActiveVideoRect.top += (newVideoRect.bottom - gActiveVideoRect.bottom);
  715.                                         }
  716.                                         newBounds = newVideoRect;
  717.                                         MapRect(&newBounds, &adjustedActiveVideoRect, &(gMonitor->portRect));
  718.                                     }
  719.                                     else        // Can't tell if we've been adjusted (digitizer rect is smaller on all sides
  720.                                         // than the active source rect)
  721.                                         {
  722.                                             newBounds = newVideoRect;
  723.                                             MapRect(&newBounds, &gActiveVideoRect, &(gMonitor->portRect));
  724.                                         }
  725.                                     width = newBounds.right - newBounds.left;
  726.                                     height = newBounds.bottom - newBounds.top;
  727.                                     result = SGSetChannelBounds(gVideoChannel, &newBounds);
  728.                                 }
  729.  
  730.                                 // Clean out the part of the port that isn't being drawn in
  731.                                 deadRgn = NewRgn();
  732.                                 if (deadRgn != nil)
  733.                                 {
  734.                                     result = SGGetChannelBounds(gVideoChannel, &boundsRect);
  735.                                     result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn);
  736.                                     EraseRgn(deadRgn);
  737.                                     DisposeRgn(deadRgn);
  738.                                 }
  739.  
  740.                                 SetPort(savedPort);
  741.  
  742.                                 // The pause that refreshes
  743.                                 result = SGPause(gSeqGrabber, false);
  744.                             }
  745.                             break;
  746.                         }
  747.                     case kSoundSettingsItem:
  748.                         {
  749.                             if ((gSeqGrabber != 0L) && (gSoundChannel != 0L))
  750.                             {
  751.                                 // Do the dialog thang
  752.                                 result = SGSettingsDialog(gSeqGrabber, gSoundChannel, 0, nil, 0L, SeqGrabberModalFilterProc, (long)StripAddress((Ptr)gMonitor));
  753.                             }
  754.                             break;
  755.                         }
  756.                     case kQuarterSizeItem:
  757.                         {
  758.                             // New width and height
  759.                             width = (gActiveVideoRect.right - gActiveVideoRect.left) / 4;
  760.                             height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 4;
  761.  
  762.                             // Set flags and menus
  763.                             gQuarterSize = true;
  764.                             gHalfSize = false;
  765.                             gFullSize = false;
  766.                             AdjustMenus();
  767.  
  768.                             // Resize the monitor
  769.                             GetPort(&savedPort);
  770.                             SetPort(gMonitor);
  771.                             result = SGPause(gSeqGrabber, true);
  772.                             result = SGGetChannelBounds(gVideoChannel, &curBounds);
  773.                             maxBoundsRect = gMonitor->portRect;
  774.                             SizeWindow(gMonitor, width, height, false);
  775.                             MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect));
  776.                             result = SGSetChannelBounds(gVideoChannel, &curBounds);
  777.  
  778.                             // Clean out part of port we're not drawing in
  779.                             deadRgn = NewRgn();
  780.                             if (deadRgn != nil)
  781.                             {
  782.                                 result = SGGetChannelBounds(gVideoChannel, &boundsRect);
  783.                                 result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn);
  784.                                 EraseRgn(deadRgn);
  785.                                 DisposeRgn(deadRgn);
  786.                             }
  787.  
  788.                             SetPort(savedPort);
  789.                             result = SGPause(gSeqGrabber, false);
  790.                             break;
  791.                         }
  792.                     case kHalfSizeItem:
  793.                         {
  794.                             // New width and height
  795.                             width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2;
  796.                             height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2;
  797.  
  798.                             // Set flags and menus
  799.                             gQuarterSize = false;
  800.                             gHalfSize = true;
  801.                             gFullSize = false;
  802.                             AdjustMenus();
  803.  
  804.                             // Resize the monitor
  805.                             GetPort(&savedPort);
  806.                             SetPort(gMonitor);
  807.                             result = SGPause(gSeqGrabber, true);
  808.                             result = SGGetChannelBounds(gVideoChannel, &curBounds);
  809.                             maxBoundsRect = gMonitor->portRect;
  810.                             SizeWindow(gMonitor, width, height, false);
  811.                             MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect));
  812.                             result = SGSetChannelBounds(gVideoChannel, &curBounds);
  813.  
  814.                             // Clean out part of port we're not drawing in
  815.                             deadRgn = NewRgn();
  816.                             if (deadRgn != nil)
  817.                             {
  818.                                 result = SGGetChannelBounds(gVideoChannel, &boundsRect);
  819.                                 result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn);
  820.                                 EraseRgn(deadRgn);
  821.                                 DisposeRgn(deadRgn);
  822.                             }
  823.  
  824.                             SetPort(savedPort);
  825.                             result = SGPause(gSeqGrabber, false);
  826.                             break;
  827.                         }
  828.                     case kFullSizeItem:
  829.                         {
  830.                             // New width and height
  831.                             width = gActiveVideoRect.right - gActiveVideoRect.left;
  832.                             height = gActiveVideoRect.bottom - gActiveVideoRect.top;
  833.  
  834.                             // Set flags and menus
  835.                             gQuarterSize = false;
  836.                             gHalfSize = false;
  837.                             gFullSize = true;
  838.                             AdjustMenus();
  839.  
  840.                             // Resize the monitor
  841.                             GetPort(&savedPort);
  842.                             SetPort(gMonitor);
  843.                             result = SGPause(gSeqGrabber, true);
  844.                             result = SGGetChannelBounds(gVideoChannel, &curBounds);
  845.                             maxBoundsRect = gMonitor->portRect;
  846.                             SizeWindow(gMonitor, width, height, false);
  847.                             MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect));
  848.                             result = SGSetChannelBounds(gVideoChannel, &curBounds);
  849.  
  850.                             // Clean out part of port we're not drawing in
  851.                             deadRgn = NewRgn();
  852.                             if (deadRgn != nil)
  853.                             {
  854.                                 result = SGGetChannelBounds(gVideoChannel, &boundsRect);
  855.                                 result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn);
  856.                                 EraseRgn(deadRgn);
  857.                                 DisposeRgn(deadRgn);
  858.                             }
  859.  
  860.                             SetPort(savedPort);
  861.                             result = SGPause(gSeqGrabber, false);
  862.                             break;
  863.                         }
  864.                     default:
  865.                         {
  866.                             break;
  867.                         }
  868.                 }
  869.             }
  870.         default:
  871.             {
  872.                 break;
  873.             }
  874.     }
  875. }
  876.  
  877. //-----------------------------------------------------------------------
  878.  
  879. static void DoAboutDialog(void)
  880. {
  881.     short itemHit;
  882.     short itemType;
  883.     Handle itemHandle;
  884.     Rect itemRect;
  885.     DialogPtr aboutDialog = GetNewDialog(kAboutDLOGID, nil, (WindowPtr) - 1L);
  886.  
  887.     // Do the boring about dialog
  888.     GetDItem(aboutDialog, kAboutOKButtonOutline, &itemType, &itemHandle, &itemRect);
  889.     SetDItem(aboutDialog, kAboutOKButtonOutline, itemType, (Handle)AboutDrawProc, &itemRect);
  890.  
  891.     ShowWindow(aboutDialog);
  892.     do
  893.     {
  894.         ModalDialog(nil, &itemHit);
  895.     } while (itemHit != kAboutOKButton);
  896.     DisposDialog(aboutDialog);
  897. }
  898.  
  899. //-----------------------------------------------------------------------
  900.  
  901. pascal void AboutDrawProc(DialogPtr theDialog,
  902.                           short theItemNum)
  903. {
  904.     PenState thePenState;
  905.     OSErr result = noErr;
  906.     Rect itemRect;
  907.     Handle itemHandle;
  908.     short itemType;
  909.  
  910.     // Set up the pen
  911.     GetPenState(&thePenState);
  912.  
  913.     GetDItem(theDialog, theItemNum, &itemType, &itemHandle, &itemRect);
  914.  
  915.     // What item do we need to draw?
  916.     switch (theItemNum)
  917.     {
  918.         case kAboutOKButtonOutline:
  919.             PenNormal();
  920.             PenMode(patCopy);
  921.             PenSize(3, 3);
  922.             InsetRect(&itemRect, -4, -4);
  923.             FrameRoundRect(&itemRect, 16, 16);
  924.             break;
  925.         default:
  926.             break;
  927.     }
  928.  
  929.     // Restore the pen
  930.     SetPenState(&thePenState);
  931. }
  932.  
  933. //-----------------------------------------------------------------------
  934.  
  935. static OSErr XorRectToRgn(Rect* srcRectA,
  936.                           Rect* srcRectB,
  937.                           RgnHandle* destRgn)
  938. {
  939.     RgnHandle srcRgnA = NewRgn();
  940.     RgnHandle srcRgnB = NewRgn();
  941.     OSErr result = noErr;
  942.  
  943.     if ((destRgn != nil) && (*destRgn != nil))
  944.     {
  945.         if ((srcRgnA != nil) && (srcRgnB != nil))
  946.         {
  947.             RectRgn(srcRgnA, srcRectA);
  948.             RectRgn(srcRgnB, srcRectB);
  949.             XorRgn(srcRgnA, srcRgnB, *destRgn);
  950.         }
  951.         else
  952.         {
  953.             result = memFullErr;
  954.         }
  955.     }
  956.     else
  957.     {
  958.         result = nilHandleErr;
  959.     }
  960.     return (result);
  961. }
  962.  
  963. //-----------------------------------------------------------------------
  964.  
  965. pascal Boolean SeqGrabberModalFilterProc(DialogPtr theDialog,
  966.                                          EventRecord* theEvent,
  967.                                          short* itemHit,
  968.                                          long refCon)
  969. {
  970.     // Ordinarily, if we had multiple windows we cared about, we'd handle
  971.     // updating them in here, but since we don't, we'll just clear out
  972.     // any update events meant for us
  973.  
  974.     Boolean handled = false;
  975.  
  976.     if ((theEvent->what == updateEvt) && ((WindowPtr)theEvent->message == (WindowPtr)refCon))
  977.     {
  978.         BeginUpdate((WindowPtr)refCon);
  979.         EndUpdate((WindowPtr)refCon);
  980.         handled = true;
  981.     }
  982.     return (handled);
  983. }
  984.  
  985. //-----------------------------------------------------------------------
  986.  
  987. static void DoQuit(void)
  988. {
  989.     ComponentResult result = noErr;
  990.  
  991.     // Clean up
  992.     if (gSeqGrabber != 0L)
  993.     {
  994.         result = CloseComponent(gSeqGrabber);
  995.         gSeqGrabber = 0L;
  996.     }
  997.     if (gMonitor != nil)
  998.     {
  999.         DisposeWindow(gMonitor);
  1000.     }
  1001.  
  1002.     // Set quit flag
  1003.     gQuitFlag = true;
  1004.  
  1005.     ExitMovies();
  1006. }
  1007.  
  1008. //-----------------------------------------------------------------------
  1009.  
  1010.