home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / Documentation / develop articles / develop Issue 19 / MyCaptureApp / MySGStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-01  |  26.8 KB  |  994 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        MySGStuff.c
  3.     
  4.     Contains:    Sequence grabber code.
  5.  
  6.     Written by:    John Wang
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <5>        07/01/94    JW        1.0        Added workaround for AV machines that don't initialize video
  13.                                             settings properly.  The fix is to call GetSetting and then SetSettings
  14.                                             when no preferences is loaded for the channel.
  15.         <4>        04/25/94    JW        1.0b4.  Fixed minor bug in 1.0b3 where if the sound channel wasn't
  16.                                             opened, then MyUpdateChannels would fail.
  17.         <3>        04/18/94    JW        1.0b3.  Support for multiple capture channels.
  18.         <2>        04/08/94    JW        1.0b2.  Support for preferences file added so that channel
  19.                                             settings is preserved.
  20.         <1>        04/04/94    JW        1.0b1    Started and created as 1.0b1.
  21.  
  22.     To Do:
  23.     
  24. */
  25.  
  26. #ifdef THINK_C
  27. #define        applec
  28. #endif
  29.  
  30. #include    "MyHeaders"
  31. /*
  32. #include    <Types.h>
  33. #include    <Memory.h>
  34. #include    <QuickDraw.h>
  35. #include    <Palettes.h>
  36. #include    <QDOffscreen.h>
  37. #include    <Errors.h>
  38. #include    <Fonts.h>
  39. #include    <Dialogs.h>
  40. #include    <Windows.h>
  41. #include    <Menus.h>
  42. #include    <Events.h>
  43. #include    <Desk.h>
  44. #include    <DiskInit.h>
  45. #include    <OSUtils.h>
  46. #include    <Resources.h>
  47. #include    <ToolUtils.h>
  48. #include    <AppleEvents.h>
  49. #include    <EPPC.h>
  50. #include    <GestaltEqu.h>
  51. #include    <Processes.h>
  52. #include    <Balloons.h>
  53. #include    <Aliases.h>
  54. #include    <MixedMode.h>
  55. #include    <Scrap.h>
  56. #include    <LowMem.h>
  57.  
  58. #include    <Movies.h>
  59. #include    <QuickTimeComponents.h>
  60. */
  61.  
  62. #include    "MyCaptureAppShell.h"
  63. #include    "MySGStuff.h"
  64. #include    "MyUtils.h"
  65.  
  66. /* ------------------------------------------------------------------------- */
  67.  
  68. //    Contains application runtime variables.  Stored in window refCon as handle block.
  69. struct WindowInfo {
  70.     ComponentInstance        theSG;
  71.     SGChannel                channel[kMAXCHANNELS];
  72.     Boolean                    recordPlayThru;
  73.     Boolean                    createSeparateFiles;
  74. };
  75. typedef        struct WindowInfo WindowInfo, *WindowInfoPtr, **WindowInfoHandle;
  76.  
  77. //    Contains compression settings for the video channel.  Used in SGInfo.
  78. struct CompressionInfo {
  79.     OSType        compressorType;
  80.     short        depth;
  81.     CodecQ        spatialQuality;
  82.     CodecQ        temporalQuality;
  83.     long        keyFrameRate;
  84. };
  85. typedef        struct CompressionInfo CompressionInfo;
  86.  
  87. //    Contains Sequence Grabber channel information.  Stored as a global variable.
  88. struct SGInfo {
  89.     CompressionInfo        cInfo;
  90.     OSType                channelType[kMAXCHANNELS];
  91.     Handle                channelName[kMAXCHANNELS];
  92.     UserData            channelSettings[kMAXCHANNELS];
  93. };
  94. typedef        struct SGInfo SGInfo;
  95. SGInfo        gSGInfo;
  96.  
  97. //    Boolean variable.  true is QuickTime 2.0 or later.  false otherwise i.e. 1.6.2.
  98. Boolean        gHasQuickTime20;
  99.  
  100. /* ------------------------------------------------------------------------- */
  101.  
  102. //    MyInitialize is called at init time after the toolbox is initialized.  This routine is
  103. //    called only once.
  104.  
  105. long MyInitialize()
  106. {
  107.     long                    err;
  108.     long                    QDfeature;
  109.     short                    myRefNum;
  110.     short                    i;
  111.     ComponentDescription    cd, theCD;
  112.     Component                aComponent;
  113.     Boolean                    done;
  114.     MenuHandle                mHandle;
  115.     
  116.     //    We require QuickTime so make sure it is available.
  117.     err = Gestalt(gestaltQuickTime, &QDfeature);
  118.     if ( err != noErr )
  119.         return ( err );
  120.         
  121.     //    Check for QuickTime 2.0 or later.
  122.     gHasQuickTime20 = ((QDfeature >> 16) & 0xffff) >= 0x200;
  123.     
  124.     //    Start the engine.
  125.     err = EnterMovies();
  126.     if ( err != noErr )
  127.         return ( err) ;
  128.     
  129.     //    Find out what sequence grabber channels are available by searching all sequence
  130.     //    grabber channel components.  Get channelType[] and channelName[].
  131.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  132.         gSGInfo.channelType[i] = 0;
  133.         gSGInfo.channelName[i] = nil;
  134.     }
  135.     cd.componentType = SeqGrabChannelType;
  136.     cd.componentSubType = 0;
  137.     cd.componentManufacturer = 0;
  138.     cd.componentFlags = 0;
  139.     cd.componentFlagsMask = 0;
  140.     aComponent = 0;
  141.     for ( i=0, done=false; i<kMAXCHANNELS && !done; i++ ) {
  142.         aComponent = FindNextComponent(aComponent, &cd);
  143.         if (aComponent != 0) {
  144.             gSGInfo.channelName[i] = NewHandle(4);
  145.             GetComponentInfo(aComponent, &theCD, gSGInfo.channelName[i], nil, nil);
  146.             gSGInfo.channelType[i] = theCD.componentSubType;
  147.         } else
  148.             done = true;
  149.     }
  150.  
  151.     //    Read preferences for compression settings and
  152.     //    channelSettings[] (if channel has been previously found).
  153.     if ( (myRefNum = readPreferencesFile()) != -1 ) {
  154.         //    File opened.
  155.         Handle            myHandle;
  156.  
  157.         //    Get Compression info.
  158.         myHandle = Get1Resource('INFO', 128);
  159.         if ( myHandle != nil ) {
  160.             DetachResource(myHandle);
  161.             HLock(myHandle);
  162.             BlockMove(*myHandle, &(gSGInfo.cInfo), sizeof(CompressionInfo));
  163.             HUnlock(myHandle);
  164.             DisposeHandle(myHandle);
  165.         } else {
  166.             //    If no such resource, then manually udpate the values.
  167.             gSGInfo.cInfo.compressorType = 'raw ';
  168.             gSGInfo.cInfo.depth = 16;
  169.             gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  170.             gSGInfo.cInfo.temporalQuality = 0;
  171.             gSGInfo.cInfo.keyFrameRate = 0;
  172.         }
  173.         
  174.         //    Get all the saved channel settings for the channels that are available.
  175.         for ( i=0; i< kMAXCHANNELS; i++ ) {
  176.             if (gSGInfo.channelType[i] != 0) {
  177.                 myHandle = Get1Resource(gSGInfo.channelType[i], 128);
  178.                 if ( myHandle != nil ) {
  179.                     err = NewUserDataFromHandle(myHandle, &(gSGInfo.channelSettings[i]));
  180.                     if ( err != noErr ) {
  181.                         ReportWarning("\pCould not create user data from handle: ", err);
  182.                         gSGInfo.channelSettings[i] = nil;
  183.                     }
  184.                 } else
  185.                     gSGInfo.channelSettings[i] = nil;
  186.             } else
  187.                 gSGInfo.channelSettings[i] = nil;
  188.         }
  189.         
  190.         //    Finished.  Close the preferences file.
  191.         closePreferencesFile(myRefNum);
  192.     } else {
  193.         //    If no preferences file, then use default values.
  194.         gSGInfo.cInfo.compressorType = 'raw ';
  195.         gSGInfo.cInfo.depth = 16;
  196.         gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  197.         gSGInfo.cInfo.temporalQuality = 0;
  198.         gSGInfo.cInfo.keyFrameRate = 0;
  199.         for ( i=0; i< kMAXCHANNELS; i++ )
  200.             gSGInfo.channelSettings[i] = nil;
  201.     }
  202.  
  203.     //    Add the channel names to the menu.
  204.     mHandle = GetMHandle(kMENU_SETTINGSID);
  205.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  206.         if (gSGInfo.channelType[i] != 0) {
  207.             Str255        myStr;
  208.             
  209.             BlockMove("   Disable", &myStr[1], 11);
  210.             BlockMove(*(gSGInfo.channelName[i]), &myStr[11], **(gSGInfo.channelName[i]) + 1);
  211.             myStr[0] = 11 + **(gSGInfo.channelName[0]);
  212.             myStr[11] = ' ';
  213.             AppendMenu(mHandle, (unsigned char *) *(gSGInfo.channelName[i]));
  214.             AppendMenu(mHandle, myStr);
  215.         }
  216.     }
  217.  
  218.     return ( noErr );
  219. }
  220.  
  221. void MyFinishup()
  222. {
  223.     long                err;
  224.     short                myRefNum, i;
  225.     
  226.     //    Should close all windows.  But, since we know this app only supports one window, we
  227.     //    don't need to loop.
  228.     MyClose();
  229.  
  230.     //    Write preferences file for all channel settings and compression settings.
  231.     if ((myRefNum = writePreferencesFile()) != -1) {
  232.         Handle            mySetting, myInfo;
  233.         
  234.         //    Write the compressor settings to preferences file.
  235.         myInfo = NewHandle(sizeof(CompressionInfo));
  236.         if ( myInfo == nil ) {
  237.             ReportWarning("\pCound not create compressor settings handle.", 0);
  238.         } else {
  239.             HLock((Handle) myInfo);
  240.             BlockMove(&(gSGInfo.cInfo), *myInfo, sizeof(CompressionInfo));
  241.             HUnlock((Handle) myInfo);
  242.             AddResource(myInfo, 'INFO', 128, "\pCompression Settings.");
  243.         }
  244.         
  245.         //    Write out channel settings.
  246.         for ( i=0; i< kMAXCHANNELS; i++ ) {
  247.             if (gSGInfo.channelType[i] != 0 && gSGInfo.channelSettings[i] != nil ) {
  248.                 mySetting = NewHandle(4);
  249.                 if ( mySetting == nil ) {
  250.                     ReportWarning("\pCound not create settings handle.", 0);
  251.                 } else {
  252.                     PutUserDataIntoHandle(gSGInfo.channelSettings[i], mySetting);
  253.                     AddResource(mySetting, gSGInfo.channelType[i], 128, "\pSettings.");
  254.                 }
  255.             } else
  256.                 gSGInfo.channelSettings[i] = nil;
  257.         }
  258.         
  259.         closePreferencesFile(myRefNum);
  260.     } else
  261.         ReportWarning("\pSorry.  Could not create preferences file.", 0);
  262. }
  263.  
  264. void MyIdle()
  265. {
  266.     WindowPtr        theWindow;
  267.  
  268.     theWindow = FrontWindow();
  269.     
  270.     //    Only one window allowed to be opened at a time.
  271.     if ( theWindow != nil ) {    //    Yes, window open.
  272.         WindowInfoHandle    myWindowInfo;
  273.         
  274.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  275.         if ((**myWindowInfo).theSG != nil)
  276.             SGIdle((**myWindowInfo).theSG);
  277.     }
  278. }
  279.  
  280. long MyYieldTime(long message)
  281. {
  282.     if ( message )
  283.         //    Resume message
  284.         return ( 0 );
  285.     else
  286.         //    Suspend message
  287.         return ( 30 );
  288. }
  289.  
  290. void MyAdjustMenus()
  291. {
  292.     MenuHandle            mHandle;
  293.     WindowPtr            theWindow;
  294.     WindowInfoHandle    myWindowInfo;
  295.     short                 i;
  296.     
  297.     theWindow = FrontWindow();
  298.     
  299.     myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  300.  
  301.     //    Allow only one window to be opened.
  302.     if ( theWindow != nil ) {    //    Yes, window open.
  303.         //    File menu.
  304.         mHandle = GetMHandle(kMENU_FILEID);
  305.         DisableItem(mHandle, kMENU_FILENEW);
  306.         EnableItem(mHandle, kMENU_FILECLOSE);
  307.         
  308.         //    Settings menu.
  309.         mHandle = GetMHandle(kMENU_SETTINGSID);
  310.         EnableItem(mHandle, 0);
  311.         for ( i=0; i<kMAXCHANNELS; i++ ) {
  312.             if (gSGInfo.channelType[i] != 0) {
  313.                 if ( (**myWindowInfo).channel[i] != nil ) {
  314.                     EnableItem(mHandle, i*2+1);
  315.                     EnableItem(mHandle, i*2+2);
  316.                 } else {
  317.                     DisableItem(mHandle, i*2+1);
  318.                     DisableItem(mHandle, i*2+2);
  319.                 }
  320.             }
  321.         }
  322.  
  323.         //    Resize menu.
  324.         mHandle = GetMHandle(kMENU_RESIZEID);
  325.         EnableItem(mHandle, 0);
  326.  
  327.         //    Special menu.
  328.         mHandle = GetMHandle(kMENU_SPECIALID);
  329.         EnableItem(mHandle, 0);
  330.         CheckItem(mHandle, kMENU_SPECIALPLAYTHRU, (**myWindowInfo).recordPlayThru);
  331.         if ( !gHasQuickTime20 ) {
  332.             (**myWindowInfo).createSeparateFiles = false;
  333.             DisableItem(mHandle, kMENU_SPECIALSEPARATEFILES);
  334.         } else
  335.             EnableItem(mHandle, kMENU_SPECIALSEPARATEFILES);
  336.         CheckItem(mHandle, kMENU_SPECIALSEPARATEFILES, (**myWindowInfo).createSeparateFiles);
  337.     
  338.         //    Record menu.
  339.         mHandle = GetMHandle(kMENU_RECORDID);
  340.         EnableItem(mHandle, 0);
  341.  
  342.     } else {    //    No window open.
  343.         //    File menu.
  344.         mHandle = GetMHandle(kMENU_FILEID);
  345.         EnableItem(mHandle, kMENU_FILENEW);
  346.         DisableItem(mHandle, kMENU_FILECLOSE);
  347.  
  348.         //    Settings menu.
  349.         mHandle = GetMHandle(kMENU_SETTINGSID);
  350.         DisableItem(mHandle, 0);
  351.         for ( i=0; i<kMAXCHANNELS; i++ ) {
  352.             if (gSGInfo.channelType[i] != 0) {
  353.                 EnableItem(mHandle, i*2);
  354.                 EnableItem(mHandle, i*2+1);
  355.             }
  356.         }
  357.  
  358.         //    Resize menu.
  359.         mHandle = GetMHandle(kMENU_RESIZEID);
  360.         DisableItem(mHandle, 0);
  361.  
  362.         //    Special menu.
  363.         mHandle = GetMHandle(kMENU_SPECIALID);
  364.         DisableItem(mHandle, 0);
  365.         CheckItem(mHandle, kMENU_SPECIALPLAYTHRU, false);
  366.         CheckItem(mHandle, kMENU_SPECIALSEPARATEFILES, false);
  367.  
  368.         //    Record menu.
  369.         mHandle = GetMHandle(kMENU_RECORDID);
  370.         DisableItem(mHandle, 0);
  371.     }
  372.     
  373.     DrawMenuBar();
  374. }
  375.  
  376. /* ------------------------------------------------------------------------- */
  377.  
  378. void MyNew()
  379. {
  380.     long                    err;
  381.     WindowPtr                myWindow;
  382.     Rect                    myBounds = {42, 4, 282, 324};
  383.     WindowInfoHandle        myWindowInfo;
  384.     short                    i, videoChannel, soundChannel;
  385.     
  386.     myWindow = nil;
  387.     myWindowInfo = nil;
  388.     
  389.     //    Create window along with window info record.
  390.     myWindow = NewCWindow(0L, &myBounds, "\pCapture window", 1, documentProc, (WindowPtr) -1, true, 0L);
  391.     if (myWindow == nil) {
  392.         ReportWarning("\pCould not create new window.",0);
  393.         goto bail;
  394.     }
  395.     SetGWorld((CGrafPtr) myWindow, GetMainDevice());
  396.     myWindowInfo = (WindowInfoHandle) NewHandleClear(sizeof(WindowInfo));
  397.     if ( myWindowInfo == nil ) {
  398.         ReportWarning("\pCould not create window info handle.", 0);
  399.         goto bail;
  400.     }
  401.     MoveHHi((Handle) myWindowInfo);
  402.     HLock((Handle) myWindowInfo);
  403.     SetWRefCon(myWindow, (long) myWindowInfo);
  404.     (**myWindowInfo).recordPlayThru = false;
  405.     (**myWindowInfo).createSeparateFiles = false;
  406.     
  407.     //    Open sequence grabber and initialize the sequence grabber.
  408.     (**myWindowInfo).theSG = OpenDefaultComponent(SeqGrabComponentType, 0);
  409.     if ( (**myWindowInfo).theSG == nil) {
  410.         ReportWarning("\pOpenDefaultComponent failed to open default sequence grabber component.", 0);
  411.         goto bail;
  412.     }
  413.     err = SGInitialize((**myWindowInfo).theSG);
  414.     if ( err != noErr ) {
  415.         ReportWarning("\pCould not initialize sequence grabber: ", err);
  416.         goto bail;
  417.     }
  418.     
  419.     //    First things first, set the GWorld to the newly created window.
  420.     err = SGSetGWorld((**myWindowInfo).theSG, (CGrafPtr) myWindow, GetMainDevice());
  421.     if ( err != noErr ) {
  422.         ReportWarning("\pCould not SGSetGWorld: ", err);
  423.         goto bail;
  424.     }
  425.     
  426.     //    Now, let's create the different channels.
  427.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  428.         //    If the channel type exists, then create it.
  429.         if ( gSGInfo.channelType[i] != 0) {
  430.  
  431.             //    Create channel.
  432.             err = SGNewChannel((**myWindowInfo).theSG, gSGInfo.channelType[i],
  433.                                         &((**myWindowInfo).channel[i]));
  434.             if ( err != noErr ) {
  435.                 //    Fail with this channel.
  436.                 ReportWarning("\pCould not open channel: ", err);
  437.                 (**myWindowInfo).channel[i] = 0;
  438.             } else {
  439.                 //    Set the settings retrieved from preferences file.
  440.                 if ( gSGInfo.channelSettings[i] != nil ) {
  441.                     err = SGSetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  442.                                             gSGInfo.channelSettings[i], 0);
  443.                     if ( err != noErr ) {
  444.                         ReportWarning("\pFailed to set channel settings: ", err);
  445.                     }
  446.                 } else {
  447.                 //    Workaround for AV vdigs that don't initialize correctly.
  448.                     err = SGGetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  449.                                             &(gSGInfo.channelSettings[i]), 0);
  450.                     if ( err != noErr ){
  451.                         ReportWarning("\pCould not get channel settings: ", err);
  452.                         gSGInfo.channelSettings[i] = nil;
  453.                     }
  454.                     err = SGSetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  455.                                             gSGInfo.channelSettings[i], 0);
  456.                     if ( err != noErr ) {
  457.                         ReportWarning("\pFailed to set channel settings: ", err);
  458.                     }
  459.                 }
  460.             }
  461.         } else
  462.             (**myWindowInfo).channel[i] = 0;
  463.     }
  464.     
  465.     //    If there is a video channel, then set the compression settings.
  466.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  467.         if ( gSGInfo.channelType[i] == VideoMediaType )
  468.             videoChannel = i;
  469.     }
  470.     if ( videoChannel >= 0 ) {
  471.         err = SGSetVideoCompressorType((**myWindowInfo).channel[videoChannel], gSGInfo.cInfo.compressorType);
  472.         if ( err != noErr ) {
  473.             ReportWarning("\pCould not set video compressor type: ", err);
  474.         }
  475.         err = SGSetVideoCompressor((**myWindowInfo).channel[videoChannel], gSGInfo.cInfo.depth, nil,
  476.                         gSGInfo.cInfo.spatialQuality, gSGInfo.cInfo.temporalQuality, gSGInfo.cInfo.keyFrameRate);
  477.         if ( err != noErr ) {
  478.             ReportWarning("\pCould not set video compressor info: ", err);
  479.         }
  480.     }
  481.     
  482.     //    Update the channels.
  483.     err = MyUpdateChannels(myWindow);
  484.     if ( err != noErr ) {
  485.         ReportWarning("\pCould not update channels: ", err);
  486.         goto bail;
  487.     }
  488.     
  489.     //    Start the preview now that everything is set up!!!
  490.     err = SGStartPreview((**myWindowInfo).theSG);
  491.     if ( err != noErr ) {
  492.         ReportWarning("\pCould not start preview.", err);
  493.         goto bail;
  494.     }
  495.     
  496.     return;
  497.  
  498. bail:
  499.     SysBeep(50);
  500.     if ( (**myWindowInfo).theSG != nil )
  501.         CloseComponent((**myWindowInfo).theSG);
  502.     if ( myWindowInfo != nil )
  503.         DisposHandle((Handle) myWindowInfo);
  504.     if ( myWindow != nil )
  505.         DisposeWindow(myWindow);
  506.     return;
  507. }
  508.  
  509. void MyClose()
  510. {
  511.     long                err;
  512.     WindowPtr            closeWindow;
  513.     WindowInfoHandle        myWindowInfo;
  514.     short                i, videoChannel;
  515.     
  516.     closeWindow = FrontWindow();
  517.     if ( closeWindow == nil )
  518.         return;
  519.     myWindowInfo = (WindowInfoHandle) GetWRefCon(closeWindow);
  520.  
  521.     //    If there is a video channel, then get the compression settings.
  522.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  523.         if ( gSGInfo.channelType[i] == VideoMediaType )
  524.             videoChannel = i;
  525.     }
  526.     if ( videoChannel >= 0 ) {
  527.         err = SGGetVideoCompressorType((**myWindowInfo).channel[videoChannel], &gSGInfo.cInfo.compressorType);
  528.         if ( err != noErr )
  529.             gSGInfo.cInfo.compressorType = 'raw ';
  530.         err = SGGetVideoCompressor((**myWindowInfo).channel[videoChannel], &gSGInfo.cInfo.depth, nil,
  531.                         &gSGInfo.cInfo.spatialQuality, &gSGInfo.cInfo.temporalQuality,
  532.                         &gSGInfo.cInfo.keyFrameRate);
  533.         if ( err != noErr ) {
  534.             gSGInfo.cInfo.depth = 16;
  535.             gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  536.             gSGInfo.cInfo.temporalQuality = 0;
  537.             gSGInfo.cInfo.keyFrameRate = 0;
  538.         }
  539.     }
  540.     
  541.     //    Get the video settings.
  542.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  543.     
  544.         //    Set the video settings retrieved from preferences file.
  545.         if ( gSGInfo.channelType[i] != 0 && (**myWindowInfo).channel[i] != 0) {
  546.             err = SGGetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  547.                                     &(gSGInfo.channelSettings[i]), 0);
  548.             if ( err != noErr ){
  549.                 ReportWarning("\pCould not get channel settings: ", err);
  550.                 gSGInfo.channelSettings[i] = nil;
  551.             }
  552.         }
  553.     }
  554.         
  555.     //    Close the component. 
  556.     if ( (**myWindowInfo).theSG != nil )
  557.         CloseComponent((**myWindowInfo).theSG);
  558.     
  559.     if ( myWindowInfo != nil )
  560.         DisposHandle((Handle) myWindowInfo);
  561.     
  562.     DisposeWindow(closeWindow);
  563. }
  564.  
  565. /* ------------------------------------------------------------------------- */
  566.  
  567. void MySettings(short item)
  568. {
  569.     long            err;
  570.     WindowPtr        theWindow;
  571.     short            index;
  572.     
  573.     theWindow = FrontWindow();
  574.     
  575.     //    Allow only one window to be opened.
  576.     if ( theWindow != nil ) {    //    Yes, window open.
  577.         WindowInfoHandle    myWindowInfo;
  578.         
  579.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  580.         
  581.         index = (item - 1) / 2;
  582.         if ( (item & 1) == 0 ) {
  583.             //    Pause before making changes.
  584.             err = SGPause((**myWindowInfo).theSG, true);
  585.             if ( err != noErr ) {
  586.                 ReportWarning("\pCould not pause preview: ", err);
  587.             }
  588.  
  589.             //    Disable channel.
  590.             if ( (**myWindowInfo).channel[index] != 0 ) {
  591.                 SGDisposeChannel((**myWindowInfo).theSG, (**myWindowInfo).channel[index]);
  592.                 (**myWindowInfo).channel[index] = 0;
  593.             }
  594.             
  595.             err = SGPause((**myWindowInfo).theSG, false);
  596.             if ( err != noErr ) {
  597.                 ReportWarning("\pCould not pause preview: ", err);
  598.             }
  599.  
  600.         } else {
  601.             //    Simply call SGSettingsDialog!  That simple!
  602.             SGSettingsDialog((**myWindowInfo).theSG, (**myWindowInfo).channel[index], 0, nil, DoTheRightThing, nil , 0);
  603.         }
  604.     }
  605. }
  606.  
  607. void MyResize(short item)
  608. {
  609.     WindowPtr        theWindow;
  610.     long            err;
  611.     Boolean            sizeChanged;
  612.     short            width, height;
  613.     
  614.     theWindow = FrontWindow();
  615.     
  616.     //    Allow only one window to be opened.
  617.     if ( theWindow != nil ) {    //    Yes, window open.
  618.         WindowInfoHandle    myWindowInfo;
  619.         
  620.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  621.         sizeChanged = false;
  622.         switch ( item ) {
  623.             case 1:
  624.                 width = 160; height = 120;
  625.                 sizeChanged = true;
  626.                 break;
  627.             case 2:
  628.                 width = 240; height = 180;
  629.                 sizeChanged = true;
  630.                 break;
  631.             case 3:
  632.                 width = 320; height = 240;
  633.                 sizeChanged = true;
  634.                 break;
  635.             case 5:
  636.                 sizeChanged = GetCustomSize(&width, &height);
  637.                 break;
  638.         }
  639.         if ( sizeChanged ) {
  640.             //    Pause the sequence grabber before resizing window.
  641.             err = SGPause((**myWindowInfo).theSG, true);
  642.             if ( err != noErr ) {
  643.                 ReportWarning("\pCould not pause preview: ", err);
  644.             }
  645.             
  646.             //    Resize and then update the video channel.
  647.             SizeWindow(theWindow, width, height, false);
  648.             err = MyUpdateChannels(theWindow);
  649.             if ( err != noErr ) {
  650.                 ReportWarning("\pCould not update channels: ", err);
  651.             }
  652.             
  653.             //    OK.  We can restart again.
  654.             err = SGPause((**myWindowInfo).theSG, false);
  655.             if ( err != noErr ) {
  656.                 ReportWarning("\pCould not pause preview: ", err);
  657.             }
  658.         }
  659.     }
  660.     
  661. }
  662.  
  663. void MySpecial(short item)
  664. {
  665.     WindowPtr        theWindow;
  666.     long            err;
  667.     Boolean            updateFlag;
  668.     
  669.     theWindow = FrontWindow();
  670.     
  671.     //    Allow only one window to be opened.
  672.     if ( theWindow != nil ) {    //    Yes, window open.
  673.         WindowInfoHandle    myWindowInfo;
  674.         
  675.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  676.         updateFlag = false;
  677.         switch ( item ) {
  678.             case kMENU_SPECIALPLAYTHRU:
  679.                 (**myWindowInfo).recordPlayThru = !(**myWindowInfo).recordPlayThru;
  680.                 updateFlag = true;
  681.                 break;
  682.             case kMENU_SPECIALSEPARATEFILES:
  683.                 (**myWindowInfo).createSeparateFiles = !(**myWindowInfo).createSeparateFiles;
  684.                 break;
  685.         }
  686.         
  687.         //    Only update if needed.
  688.         if ( updateFlag ) {
  689.             //    Pause before changes.
  690.             err = SGPause((**myWindowInfo).theSG, true);
  691.             if ( err != noErr ) {
  692.                 ReportWarning("\pCould not pause preview: ", err);
  693.             }
  694.             
  695.             //    Update the channels.
  696.             err = MyUpdateChannels(theWindow);
  697.             if ( err != noErr ) {
  698.                 ReportWarning("\pCould not update channels: ", err);
  699.             }
  700.             
  701.             //    OK to continue.
  702.             err = SGPause((**myWindowInfo).theSG, false);
  703.             if ( err != noErr ) {
  704.                 ReportWarning("\pCould not pause preview: ", err);
  705.             }
  706.         }
  707.     }
  708. }
  709.  
  710. void MyRecord()
  711. {
  712.     WindowPtr            theWindow;
  713.     long                err;
  714.     StandardFileReply    reply;
  715.     ComponentInstance    mySG;
  716.     AliasHandle            alias;
  717.     SGOutput            output;
  718.     short                i;
  719.     
  720.     theWindow = FrontWindow();
  721.     
  722.     //    Allow only one window to be opened.
  723.     if ( theWindow != nil ) {    //    Yes, window open.
  724.         WindowInfoHandle    myWindowInfo;
  725.         
  726.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  727.         mySG = (**myWindowInfo).theSG;
  728.         if ( mySG != nil ) {
  729.             
  730.             if ( (**myWindowInfo).createSeparateFiles ) {
  731.                 for ( i=0; i<kMAXCHANNELS; i++ ) {
  732.                     if ( (**myWindowInfo).channel[i] != 0) {
  733.                         StandardPutFile("\PName of multiple file:", "\pMovie #", &reply);
  734.                         if (!reply.sfGood)
  735.                             return;
  736.                         err = CreateMovieFile(&(reply.sfFile), 'TVOD', smSystemScript,
  737.                             createMovieFileDeleteCurFile |
  738.                             createMovieFileDontCreateMovie |
  739.                             createMovieFileDontOpenFile, nil, nil);
  740.                         if ( err != noErr ) {
  741.                             ReportWarning("\pCould not create movie file 1: ", err);
  742.                             goto bail;
  743.                         }
  744.                         NewAlias(nil, &(reply.sfFile), &alias);
  745.                         if ( alias == nil )
  746.                             return;
  747.                         err = SGSetDataRef(mySG, (Handle) alias, 'alis', seqGrabToDisk);
  748.                         if ( err != noErr ) {
  749.                             ReportWarning("\pCould not set movie resource output: ", err);
  750.                             goto bail;
  751.                         }
  752.                         err = SGNewOutput(mySG, (Handle) alias, 'alis', seqGrabToDisk, &output);
  753.                         if ( err != noErr ) {
  754.                             ReportWarning("\pCould not create data output1: ", err);
  755.                             goto bail;
  756.                         }
  757.                         err = SGSetChannelOutput(mySG, (**myWindowInfo).channel[i], output);
  758.                         if ( err != noErr ) {
  759.                             ReportWarning("\pCould not set video channel output: ", err);
  760.                             goto bail;
  761.                         }
  762.                     }
  763.                 }
  764.             } else {
  765.                 //    If creating single file, then do this.
  766.                 StandardPutFile("\PName of new movie:", "\pMovie", &reply);
  767.                 if (!reply.sfGood)
  768.                     return;
  769.                 err = SGSetDataOutput(mySG, &reply.sfFile, seqGrabToDisk);
  770.                 if ( err != noErr ) {
  771.                     ReportWarning("\pCould not set data output: ", err);
  772.                     goto bail;
  773.                 }
  774.             }
  775.  
  776.             //    Set the window title so that the user knows that we are recording.
  777.             SetWTitle(theWindow, "\pRecording... click mouse to stop.");
  778.  
  779.             //    Start recording.
  780.             err = SGStartRecord(mySG);
  781.             if ( err != noErr ) {
  782.                 ReportWarning("\pCould not start recording.  The following error was returned: ", err);
  783.             }
  784.             
  785.             //    Keep recording until the mouse button is pressed.
  786.             while (!Button() && !err) {
  787.                 err = SGIdle(mySG);
  788.             }
  789.             
  790.             //    Stop recording.
  791.             err = SGStop(mySG);
  792.             if ( err != noErr ) {
  793.                 ReportWarning("\pCould not stop sequence grabber: ", err);
  794.                 goto bail;
  795.             } else
  796.                 SetWTitle(theWindow, "\pMovie captured.");
  797.  
  798.             //    Start preview again.
  799.  
  800.     err = MyUpdateChannels(theWindow);
  801.     if ( err != noErr ) {
  802.         ReportWarning("\pCould not update channels: ", err);
  803.         goto bail;
  804.     }
  805.     
  806.             err = SGStartPreview((**myWindowInfo).theSG);
  807.             if ( err != noErr ) {
  808.                 ReportWarning("\pCould not start preview: ", err);
  809.                 goto bail;
  810.             }
  811.             
  812.             //    Reset the window title.
  813.             SetWTitle(theWindow, "\pCapture window");
  814.  
  815.             FlushEvents(mDownMask | mUpMask, 0);
  816.         }
  817.     }
  818.     
  819. bail:
  820.     return;
  821. }
  822.  
  823. void MyDrag(WindowPtr theWindow, Point where)
  824. {
  825.     long            err;
  826.  
  827.     //    Allow only one window to be opened.
  828.     if ( theWindow != nil ) {    //    Yes, window open.
  829.         WindowInfoHandle    myWindowInfo;
  830.         
  831.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  832.         if ((**myWindowInfo).theSG != nil)
  833.             //    Pause preview.
  834.             err = SGPause((**myWindowInfo).theSG, true);
  835.             if ( err != noErr ) {
  836.                 ReportWarning("\pCould no pause preview: ", err);
  837.             }
  838.             
  839.             //    Drag window.
  840.             DragWindow (theWindow, where, &qd.screenBits.bounds);
  841.             
  842.             //    OK to restart preview.
  843.             err = SGPause((**myWindowInfo).theSG, false);
  844.             if ( err != noErr ) {
  845.                 ReportWarning("\pCould not pause preview: ", err);
  846.             }
  847.     }
  848. }
  849.  
  850. void MyUpdate(WindowPtr theWindow)
  851. {
  852.     long            err;
  853.  
  854.     //    Allow only one window to be opened.
  855.     if ( theWindow != nil ) {    //    Yes, window open.
  856.         WindowInfoHandle    myWindowInfo;
  857.         
  858.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  859.         if ((**myWindowInfo).theSG != nil)
  860.             //    Pause and continue to reset clip.
  861.             err = SGPause((**myWindowInfo).theSG, true);
  862.             if ( err != noErr ) {
  863.                 ReportWarning("\pCould not pause preview: ", err);
  864.             }
  865.             err = SGPause((**myWindowInfo).theSG, false);
  866.             if ( err != noErr ) {
  867.                 ReportWarning("\pCould not pause preview: ", err);
  868.             }
  869.     }
  870. }
  871.  
  872. long MyUpdateChannels(WindowPtr theWindow)
  873. {
  874.     long                err;
  875.     WindowInfoHandle    myWindowInfo;
  876.     long                usage;
  877.     short                i, videoChannel;
  878.     err = noErr;
  879.     myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  880.     
  881.     //    Update the video channel if it exists.
  882.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  883.         if ( gSGInfo.channelType[i] == VideoMediaType )
  884.             videoChannel = i;
  885.     }
  886.     if ( videoChannel >= 0 ) {
  887.         //    Set the bounds to the entire portRect.
  888.         err = SGSetChannelBounds((**myWindowInfo).channel[videoChannel], &(theWindow->portRect));
  889.         if ( err != noErr )
  890.             goto bail;
  891.             
  892.         //    Set the video usage depending on whether or not there is playthru.
  893.         usage = seqGrabPreview | seqGrabRecord;
  894.         if ( !((**myWindowInfo).recordPlayThru) )
  895.             usage |= seqGrabPlayDuringRecord;
  896.         err = SGSetChannelUsage((**myWindowInfo).channel[videoChannel], usage);
  897.         if ( err != noErr )
  898.             goto bail;
  899.     }
  900.  
  901.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  902.     //    Since sound may be turned off, check before setting sound usage.
  903.         if ( (gSGInfo.channelType[i] != VideoMediaType && gSGInfo.channelType[i] != 0) &&
  904.                 (**myWindowInfo).channel[i] != 0) {
  905.             err = SGSetChannelUsage((**myWindowInfo).channel[i], seqGrabPreview | seqGrabRecord |  seqGrabPlayDuringRecord);
  906.             if ( err != noErr )
  907.                 goto bail;
  908.         }
  909.     }
  910.     
  911. bail:
  912.     return ( err );
  913. }
  914.  
  915. /* ------------------------------------------------------------------------- */
  916.  
  917. Boolean GetCustomSize(short *width, short *height)
  918. {
  919.     GrafPtr        savePort;
  920.     GDHandle    saveGD;
  921.     DialogPtr    theDialog;
  922.     short        itemHit;
  923.     Str255        myStr;
  924.     Boolean        done, ret;
  925.     long        lWidth, lHeight;
  926.     
  927.     GetPort(&savePort);
  928.     saveGD = GetGDevice();
  929.     theDialog = GetNewDialog(130, nil, (WindowPtr) -1);
  930.     SetPort(theDialog);
  931.     SetGDevice(GetMainDevice());
  932.     
  933.     //    Reset data to begin.
  934.     SetText(theDialog, 4, "\p640");
  935.     SetText(theDialog, 6, "\p480");
  936.  
  937.     //    Get membershipid and each inventory id
  938.     done = false;
  939.     do {
  940.         ModalDialog(nil, &itemHit);
  941.         GetText(theDialog, 4, myStr);
  942.         StringToNum(myStr, &lWidth);
  943.         GetText(theDialog, 6, myStr);
  944.         StringToNum(myStr, &lHeight);
  945.         if (itemHit == 1 ) {
  946.             if (lWidth > 0 && lWidth <= 640 && lHeight >= 0 && lHeight <= 480)
  947.                 done = true;
  948.             else
  949.                 SysBeep(50);
  950.         }
  951.     } while ((!done) && (itemHit != 2));
  952.  
  953.     if ( itemHit == 1 ) {
  954.         GetText(theDialog, 4, myStr);
  955.         StringToNum(myStr, &lWidth);
  956.         *width = lWidth;
  957.         GetText(theDialog, 6, myStr);
  958.         StringToNum(myStr, &lHeight);
  959.         *height = lHeight;
  960.         ret = true;
  961.     } else {
  962.         ret = false;
  963.     }
  964.  
  965.     DisposeDialog(theDialog);
  966.     SetPort(savePort);
  967.     SetGDevice(saveGD);
  968.     
  969.     return ( ret );
  970. }
  971.  
  972. /* ------------------------------------------------------------------------- */
  973.  
  974. void GetText(DialogPtr theDialog, short item, Str255 myStr)
  975. {
  976.     Handle        myHandle;
  977.     Rect        myRect;
  978.     short        myType;
  979.  
  980.     GetDItem(theDialog, item, &myType, &myHandle, &myRect);
  981.     GetIText(myHandle, myStr);
  982. }
  983.  
  984. void SetText(DialogPtr theDialog, short item, Str255 myStr)
  985. {
  986.     Handle        myHandle;
  987.     Rect        myRect;
  988.     short        myType;
  989.  
  990.     GetDItem(theDialog, item, &myType, &myHandle, &myRect);
  991.     SetIText(myHandle, myStr);
  992. }
  993.  
  994.