mac/main.c

/*
    File:       HackTV.c
 
    Contains:   Hack TV routines.
            
                Refer to develop Issue 14, "Video Digitizing Under QuickTime",
                for details on this code.
                
    Written by: Gary Woodcock
    Updated by: Brian Friedkin
 
    Copyright:  © 1992-1998 by Apple Computer, Inc.
*/
 
//-----------------------------------------------------------------------
// Includes
#include <QTML.h>
#include <Menus.h>
#include <MacWindows.h>
#include <QuickDraw.h>
#include <Resources.h>
#include <Fonts.h>
#include <ToolUtils.h>
#include <QuickTimeComponents.h>
#include <Scrap.h>
#include <Printing.h>
#include <Errors.h>
#include <Folders.h>
#include <Script.h>
#include <MacMemory.h>
#include <Gestalt.h>
#include <Endian.h>
#include <Devices.h>
#include <LowMem.h>
#include <TextUtils.h>
#include "Globals.h"
#include "Common.h"
 
#define kMenuBarID 128
enum
{
    kAppleID = 128,
    kFileID,
    kEditID,
    kMonitorID
};
    
// Apple menu items
enum
{
    kAboutItem = 1
};
 
// File menu items
enum
{
    kPageSetupItem = 1,
    kPrintItem,
    kQuitItem = 4
};
 
// Edit menu items
enum
{
    kUndoItem = 1,
    kCutItem = 3,
    kCopyItem,
    kPasteItem,
    kClearItem
};
 
// Monitor menu items
enum
{
    kVideoSettingsItem = 1,
    kSoundSettingsItem,
    kRecordVideoItem = 4,
    kRecordSoundItem,
    kSplitTracksItem,
    kQuarterSizeItem = 8,
    kHalfSizeItem,
    kFullSizeItem,
    kRecordItem = 12
};
    
//-----------------------------------------------------------------------
// Globals
MenuHandle              gAppleMenu=0;
MenuHandle              gFileMenu=0;
MenuHandle              gEditMenu=0;
MenuHandle              gMonitorMenu=0;
EventRecord             gTheEvent;
 
//-----------------------------------------------------------------------
// Prototypes
static void Initialize (void);
static void DoMenuSetup (void);
static void HandleEvent (void);
static void HandleMouseDown (void);
static void AdjustMenus (void);
static void Enable (Handle menu, short item, Boolean ok);
static void HandleMenu (long menu);
static void DoQuit (void);
 
 
//-----------------------------------------------------------------------
 
void main (void)
{
    Initialize();
 
    // Eat events until done
    do
    {
        HandleEvent();
    }
    while (!gQuitFlag);
}
 
//-----------------------------------------------------------------------
 
void Initialize(void)
{
    EventRecord event;
    short   count;
 
    // Stock initialization
    InitGraf((Ptr) &qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    TEInit();
    InitDialogs(nil);
    InitCursor();
    MaxApplZone();
    for (count = 1; count <= 3; count++)
        EventAvail(everyEvent, &event);
 
    // Load the menubar
    DoMenuSetup();
 
    // Initialize QuickTime
    EnterMovies();
    
    // Startup the sequence grabber
    InitializeSequenceGrabber();
}
 
//-----------------------------------------------------------------------
 
void CreateMonitorWindow(void)
{
    gMonitor = GetNewDialog (kMonitorDLOGID, nil, (WindowPtr) -1L);
}
 
//-----------------------------------------------------------------------
 
static void
DoMenuSetup (void)
{   
    Handle  theMenuBar = GetNewMBar (kMenuBarID);
    
    // Set up our menus
    SetMenuBar (theMenuBar);
    gAppleMenu = GetMenuHandle (kAppleID);
    gFileMenu = GetMenuHandle (kFileID);
    gEditMenu = GetMenuHandle (kEditID);
    gMonitorMenu = GetMenuHandle (kMonitorID);
    AppendResMenu (gAppleMenu, 'DRVR');
    
    // Last minute adjustmentsÉ
    AdjustMenus();
}
 
//-----------------------------------------------------------------------
 
static void
HandleEvent (void)
{
    ComponentResult result = noErr;
 
    // Do system stuff
    HiliteMenu(0);
    SystemTask();
    
    // Give some time to the sequence grabber
    if (gSeqGrabber != 0L)
        result = SGIdle (gSeqGrabber);
    
    // Suck an event
    if (WaitNextEvent (everyEvent, &gTheEvent, 0, 0))
    {
        // What was it?
        switch (gTheEvent.what)
        {
            case mouseDown:
            {
                // Handle it
                HandleMouseDown();
                break;
            }
            case keyDown:
            case autoKey:
            {
                char    theChar = gTheEvent.message & charCodeMask;
                long    theMenu = MenuKey (theChar);
 
                // Handle menu command keys
                HandleMenu(theMenu);                
                break;
            }
            case updateEvt:
            {
                if ((gMonitor != nil) && ((WindowPtr) (gTheEvent.message) == (WindowPtr) gMonitor))
                {
                    SGUpdate(gSeqGrabber, ((WindowPeek)gMonitor)->updateRgn);
                    BeginUpdate (gMonitor);
                    EndUpdate (gMonitor);
                }
                break;
            }
            default:    // We don't really care about any other events, but you might, so feel free
            {
                break;
            }
        }
    }
}
 
//-----------------------------------------------------------------------
 
static void
HandleMouseDown (void)
{   
    WindowPtr   theWindow;
    short       windowCode = MacFindWindow (gTheEvent.where, &theWindow);
    
    // Where was the mouse down?
    switch (windowCode)
    {
        case inSysWindow:
        { 
            SystemClick (&gTheEvent, theWindow);
            break;
        }
        case inMenuBar:
        {
            AdjustMenus();
            HandleMenu (0L);
            break;
        }
        case inDrag:
        {
            // Was it the monitor?
            if (theWindow == gMonitor)
            {
                ComponentResult result = noErr;
                Rect            limitRect;
                RgnHandle       grayRgn = GetGrayRgn();
                Rect            boundsRect;
                
                // Find bounds
                if (grayRgn != nil)
                {
                    limitRect = (*grayRgn)->rgnBBox;
                }
                else
                {
                    limitRect = qd.screenBits.bounds;
                }
                
                // Pause the sequence grabber
                result = SGPause (gSeqGrabber, true);
                
                if (gVideoChannel != nil)
                {
                    // Drag it with the totally cool DragAlignedWindow
                    result = SGGetChannelBounds (gVideoChannel, &boundsRect);
                    DragAlignedWindow (theWindow, gTheEvent.where, &limitRect, &boundsRect, &gSeqGrabberAlignProc);
                }
                else
                {
                    DragWindow (theWindow, gTheEvent.where, &limitRect);
                }
                
                // Start up the sequence grabber
                result = SGPause (gSeqGrabber, false);
            }
            break;
        }
 
        case inGoAway:
            if (TrackGoAway(theWindow, gTheEvent.where))
                DoQuit();
            break;
 
        default:
        {
            break;
        }
    }
}
 
//-----------------------------------------------------------------------
 
static void
AdjustMenus (void)
{
    register WindowPeek     wp = nil;
    short                   kind = 0;
    Boolean                 DA = false;
    ComponentResult         result = noErr;
    
    // What kind of window is frontmost?
    wp = (WindowPeek) FrontWindow();
    kind = wp ? wp->windowKind : 0;
    DA = kind < 0;
    
    // Set our menu item states appropriately
    
    // Apple menu
    Enable ((Handle) gAppleMenu, kAboutItem, true); 
    
    // File menu
    Enable ((Handle) gFileMenu, kPageSetupItem, true);
    Enable ((Handle) gFileMenu, kPrintItem, (gVideoChannel != 0L ? true : false));
    Enable ((Handle) gFileMenu, kQuitItem, true);
 
    // Edit menu
    Enable ((Handle) gEditMenu, kUndoItem, DA);
    Enable ((Handle) gEditMenu, kCutItem, DA || (gVideoChannel != 0L));
    Enable ((Handle) gEditMenu, kCopyItem, DA || (gVideoChannel != 0L));
    Enable ((Handle) gEditMenu, kPasteItem, DA);
    Enable ((Handle) gEditMenu, kClearItem, DA);
    
    // Monitor menu
    Enable ((Handle) gMonitorMenu, kVideoSettingsItem, (gVideoChannel != 0L ? true : false));
    Enable ((Handle) gMonitorMenu, kSoundSettingsItem, (gSoundChannel != 0L ? true : false));
 
    Enable ((Handle) gMonitorMenu, kRecordVideoItem, (gVideoChannel != 0L ? true : false));
    CheckItem (gMonitorMenu, kRecordVideoItem, (gVideoChannel && gRecordVideo)? true : false );
    Enable ((Handle) gMonitorMenu, kRecordSoundItem, (gSoundChannel != 0L ? true : false));
    CheckItem (gMonitorMenu, kRecordSoundItem, (gSoundChannel && gRecordSound)? true : false );
    Enable ((Handle) gMonitorMenu, kSplitTracksItem, (gSoundChannel && gRecordSound && gVideoChannel && gRecordVideo)? true : false);
    CheckItem (gMonitorMenu, kSplitTracksItem, gSplitTracks ? true : false);
 
    Enable ((Handle) gMonitorMenu, kQuarterSizeItem, (gVideoChannel != 0L ? true : false));
    CheckItem (gMonitorMenu, kQuarterSizeItem, gQuarterSize);
    Enable ((Handle) gMonitorMenu, kHalfSizeItem, (gVideoChannel != 0L ? true : false));
    CheckItem (gMonitorMenu, kHalfSizeItem, gHalfSize);
    Enable ((Handle) gMonitorMenu, kFullSizeItem, (gVideoChannel != 0L ? true : false));
    CheckItem (gMonitorMenu, kFullSizeItem, gFullSize);
    Enable ((Handle) gMonitorMenu, kRecordItem, ((gSoundChannel && gRecordSound) || (gVideoChannel && gRecordVideo) ? true : false));
    
    // Draw it
    MacDrawMenuBar();
}
 
//-----------------------------------------------------------------------
 
static void
Enable (Handle menu, short item, Boolean ok)
{
    // Utility routine to enable and disable menu items
    if (ok)
    {
        EnableItem ((MenuHandle) menu, item);
    }
    else
    {
        DisableItem ((MenuHandle) menu, item);
    }
}
 
//-----------------------------------------------------------------------
 
static void
HandleMenu (long theMenu)
{   
    long            mSelect;
    short           menuID;
    short           menuItem;
    ComponentResult result = noErr; 
    
    // Did we get a menu?
    if (theMenu == 0L)
    {
        // Nope, get it from menu select
        mSelect = MenuSelect (gTheEvent.where);
    }
    else
    {
        // Yep, use it
        mSelect = theMenu;
    }
    
    // Decode it
    menuID = HiWord (mSelect);
    menuItem = LoWord (mSelect);
    
    // Which menu is it?
    switch (menuID)
    {
        case kAppleID:
        {
            if (menuItem == kAboutItem)
            {
                // Do the boring about box
                DoAboutDialog();
            }
            else    // It's a DA
            {
                Str255  name;
                GrafPtr savedPort;
                
                // Open the DA
                GetPort (&savedPort);
                GetMenuItemText (gAppleMenu, menuItem, name);
                OpenDeskAcc (name);
                SetPort (savedPort);
            }
            break;
        }
        case kFileID:
        {
            switch (menuItem)
            {
                case kPageSetupItem:
                    DoPageSetup();
                    break;
 
                case kPrintItem:
                    DoPrint();
                    break;
                    
                case kQuitItem:
                    DoQuit();
                    break;
            }
            break;
        }
        case kEditID:
        {
            // Is this a DA kind of thing?
            if (!SystemEdit (menuItem - 1))
            {
                // We only do cut and copy
                if ((menuItem == kCutItem) || (menuItem == kCopyItem))
                    DoCopyToClipboard();
            }
            break;
        }
        case kMonitorID:
        {
            switch (menuItem)
            {
                case kVideoSettingsItem:
                    DoVideoSettings();
                    break;
 
                case kSoundSettingsItem:
                    DoSoundSettings();
                    break;
 
                case kRecordVideoItem:
                    gRecordVideo = !gRecordVideo;
                    AdjustMenus();
                    break;
 
                case kRecordSoundItem:
                    gRecordSound = !gRecordSound;
                    AdjustMenus();
                    break;
 
                case kSplitTracksItem:
                    gSplitTracks = !gSplitTracks;
                    AdjustMenus();
                    break;
 
                case kQuarterSizeItem:
                    DoResize(4);
                    break;
 
                case kHalfSizeItem:
                    DoResize(2);
                    break;
                    
                case kFullSizeItem:
                    DoResize(1);
                    break;
                    
                case kRecordItem:
                    DoRecord();
                    break;
 
                default:
                    break;
            }
        }
        default:
            break;
    }
}
 
//-----------------------------------------------------------------------
 
static void
DoQuit (void)
{
    ComponentResult result = noErr;
    
    // Clean up
    if (gSeqGrabber != 0L)
    {
        result = CloseComponent (gSeqGrabber);
        gSeqGrabber = 0L;
    }   
    
    if (gMonitor != nil)
    {
        DisposeWindow(gMonitor);
    }
    
    // Set quit flag
    gQuitFlag = true;
    
    ExitMovies();
}
 
//-----------------------------------------------------------------------