Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
HackTV.c
/* |
File: HackTV.c |
Contains: Hack TV Routines. |
Written by: Gary Woodcock / QT Engineering |
Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved. |
Change History (most recent first): |
<1> 12/4/94 khs changed the format of the file to the new look and feel |
To Do: |
*/ |
// INCLUDES |
#include <Menus.h> |
#include <Windows.h> |
#include <QuickDraw.h> |
#include <OSEvents.h> |
#include <Resources.h> |
#include <Desk.h> |
#include <Fonts.h> |
#include <ToolUtils.h> |
#include <Scrap.h> |
#include <Printing.h> |
#include <Errors.h> |
#include <SegLoad.h> |
#include <QuickTimeComponents.h> |
#include <ImageCompression.h> |
#ifndef THINK_C |
#include <Packages.h> |
#endif THINK_C |
// CONSTANTS |
// Menu bar |
enum |
{ |
kMenuBarID = 128 |
}; |
// Menus |
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, kQuarterSizeItem = 4, kHalfSizeItem, kFullSizeItem |
}; |
// Dialog IDs |
enum |
{ |
kAboutDLOGID = 128, kMonitorDLOGID |
}; |
// Common DITL items |
enum |
{ |
kAboutOKButton = 1, kAboutOKButtonOutline |
}; |
// GLOBALS |
MenuHandle gAppleMenu; |
MenuHandle gFileMenu; |
MenuHandle gEditMenu; |
MenuHandle gMonitorMenu; |
EventRecord gTheEvent; |
Boolean gQuitFlag; |
SeqGrabComponent gSeqGrabber; |
SGChannel gVideoChannel; |
SGChannel gSoundChannel; |
WindowPtr gMonitor; |
Rect gActiveVideoRect; |
PicHandle gMonitorPICT; |
Boolean gFullSize; |
Boolean gHalfSize; |
Boolean gQuarterSize; |
THPrint gPrintRec; |
ICMAlignmentProcRecordPtr gSeqGrabberAlignProc; |
// FUNCTION PROTOTYPES |
static void DoInit(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 DoAboutDialog(void); |
static void DoQuit(void); |
pascal void AboutDrawProc(DialogPtr theDialog, |
short theItemNum); |
static OSErr XorRectToRgn(Rect* srcRectA, |
Rect* srcRectB, |
RgnHandle* destRgn); |
pascal Boolean SeqGrabberModalFilterProc(DialogPtr theDialog, |
EventRecord* theEvent, |
short* itemHit, |
long refCon); |
// FUNCTIONS |
//----------------------------------------------------------------------- |
void main(void) |
{ |
// Init |
DoInit(); |
DoMenuSetup(); |
// Eat events until done |
do |
{ |
HandleEvent(); |
} while (!gQuitFlag); |
// Take off, eh? |
ExitToShell(); |
} |
//----------------------------------------------------------------------- |
static void DoInit(void) |
{ |
ComponentDescription theDesc; |
ComponentResult result = noErr; |
Component sgCompID = 0L; |
GrafPtr savedPort; |
// Set up quit flag |
gQuitFlag = false; |
// MacMantraª |
MaxApplZone(); |
InitGraf(&qd.thePort); |
InitFonts(); |
FlushEvents(everyEvent, 0); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(0L); |
InitCursor(); |
EnterMovies(); |
MoreMasters(); |
MoreMasters(); |
MoreMasters(); |
MoreMasters(); |
// Init stuff |
gSeqGrabber = 0L; |
gVideoChannel = 0L; |
gSoundChannel = 0L; |
gMonitorPICT = nil; |
gPrintRec = (THPrint)NewHandleClear(sizeof(TPrint)); |
// Find and open a sequence grabber |
theDesc.componentType = SeqGrabComponentType; |
theDesc.componentSubType = 0L; |
theDesc.componentManufacturer = 'appl'; |
theDesc.componentFlags = 0L; |
theDesc.componentFlagsMask = 0L; |
sgCompID = FindNextComponent(nil, &theDesc); |
if (sgCompID != 0L) |
{ |
gSeqGrabber = OpenComponent(sgCompID); |
} |
// If we got a sequence grabber, set it up |
if (gSeqGrabber != 0L) |
{ |
// Get the monitor |
gMonitor = GetNewDialog(kMonitorDLOGID, nil, (WindowPtr) - 1L); |
if (gMonitor != nil) |
{ |
// Initialize the sequence grabber |
GetPort(&savedPort); |
SetPort(gMonitor); |
result = SGInitialize(gSeqGrabber); |
if (result == noErr) |
{ |
result = SGSetGWorld(gSeqGrabber, (CGrafPtr)gMonitor, nil); |
// Get a video channel |
result = SGNewChannel(gSeqGrabber, VideoMediaType, &gVideoChannel); |
if ((gVideoChannel != nil) && (result == noErr)) |
{ |
short width; |
short height; |
gQuarterSize = true; |
gHalfSize = false; |
gFullSize = false; |
result = SGGetSrcVideoBounds(gVideoChannel, &gActiveVideoRect); |
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 4; |
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 4; |
SizeWindow(gMonitor, width, height, false); |
ShowWindow(gMonitor); |
result = SGSetChannelUsage(gVideoChannel, seqGrabPreview); |
result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect)); |
} |
// Get a sound channel |
result = SGNewChannel(gSeqGrabber, SoundMediaType, &gSoundChannel); |
if ((gSoundChannel != nil) && (result == noErr)) |
{ |
result = SGSetChannelUsage(gSoundChannel, seqGrabPreview); |
} |
// Get readyÉ |
result = SGPrepare(gSeqGrabber, true, false); |
} |
// Go! |
result = SGStartPreview(gSeqGrabber); |
SetPort(savedPort); |
} |
} |
} |
//----------------------------------------------------------------------- |
static void DoMenuSetup(void) |
{ |
Handle theMenuBar = GetNewMBar(kMenuBarID); |
// Set up our menus |
SetMenuBar(theMenuBar); |
gAppleMenu = GetMHandle(kAppleID); |
gFileMenu = GetMHandle(kFileID); |
gEditMenu = GetMHandle(kEditID); |
gMonitorMenu = GetMHandle(kMonitorID); |
AddResMenu(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)) |
{ |
// Eat the update |
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 = FindWindow(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) |
{ |
// Get the alignment proc |
result = SGGetAlignmentProc(gSeqGrabber, gSeqGrabberAlignProc); |
// Drag it with the totally cool DragAlignedWindow |
// Note that the sequence grabber can get real confused when you use this |
// call if you've got multiple video channels - this'll get fixed in the |
// next release. |
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; |
} |
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, 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); |
// Draw it |
DrawMenuBar(); |
} |
//----------------------------------------------------------------------- |
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); |
GetItem(gAppleMenu, menuItem, name); |
OpenDeskAcc(name); |
SetPort(savedPort); |
} |
break; |
} |
case kFileID: |
{ |
switch (menuItem) |
{ |
case kPageSetupItem: |
{ |
// Do the page setup dialog |
PrOpen(); |
PrStlDialog(gPrintRec); |
PrClose(); |
break; |
} |
case kPrintItem: |
{ |
TPPrPort printPort; |
TPrStatus printStatus; |
// Copy a frame from the monitor |
if (gMonitorPICT != nil) |
{ |
KillPicture(gMonitorPICT); |
} |
gMonitorPICT = nil; |
result = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen); |
if ((result == noErr) && (gMonitorPICT != nil)) |
{ |
// Print it |
HLock((Handle)gMonitorPICT); |
PrOpen(); |
if (PrJobDialog(gPrintRec)) |
{ |
printPort = PrOpenDoc(gPrintRec, nil, nil); |
result = PrError(); |
PrOpenPage(printPort, 0); |
result = PrError(); |
DrawPicture(gMonitorPICT, &((**gMonitorPICT).picFrame)); |
PrClosePage(printPort); |
result = PrError(); |
PrCloseDoc(printPort); |
result = PrError(); |
if ((**gPrintRec).prJob.bJDocLoop == bSpoolLoop) |
{ |
PrPicFile(gPrintRec, 0, 0, 0, &printStatus); |
result = PrError(); |
} |
} |
PrClose(); |
result = PrError(); |
HUnlock((Handle)gMonitorPICT); |
} |
break; |
} |
case kQuitItem: |
{ |
// Let's scram |
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)) |
{ |
// Copy a frame from the monitor |
if (gMonitorPICT != nil) |
{ |
KillPicture(gMonitorPICT); |
} |
gMonitorPICT = nil; |
result = SGGrabPict(gSeqGrabber, &gMonitorPICT, nil, 0, grabPictOffScreen); |
if ((result == noErr) && (gMonitorPICT != nil)) |
{ |
result = ZeroScrap(); |
HLock((Handle)gMonitorPICT); |
result = PutScrap(GetHandleSize((Handle)gMonitorPICT), 'PICT', *(Handle)gMonitorPICT); |
HUnlock((Handle)gMonitorPICT); |
if (result != noErr) |
{ |
// Cut or copy failed, probably due to lack of memory |
} |
} |
} |
} |
break; |
} |
case kMonitorID: |
{ |
switch (menuItem) |
{ |
short width; |
short height; |
Rect curBounds; |
Rect curVideoRect; |
Rect newVideoRect; |
Rect newBounds; |
Rect maxBoundsRect; |
GrafPtr savedPort; |
RgnHandle deadRgn; |
Rect boundsRect; |
case kVideoSettingsItem: |
{ |
if ((gSeqGrabber != 0L) && (gVideoChannel != 0L)) |
{ |
Rect newActiveVideoRect; |
Rect adjustedActiveVideoRect; |
// Get our current state |
result = SGGetChannelBounds(gVideoChannel, &curBounds); |
result = SGGetVideoRect(gVideoChannel, &curVideoRect); |
// Pause |
result = SGPause(gSeqGrabber, true); |
// Do the dialog thang |
result = SGSettingsDialog(gSeqGrabber, gVideoChannel, 0, nil, 0L, SeqGrabberModalFilterProc, (long)StripAddress((Ptr)gMonitor)); |
// What happened? |
result = SGGetVideoRect(gVideoChannel, &newVideoRect); |
result = SGGetSrcVideoBounds(gVideoChannel, &newActiveVideoRect); |
// Set up our port |
GetPort(&savedPort); |
SetPort(gMonitor); |
// Has our active rect changed? |
// If so, it's because our video standard changed (e.g., NTSC to PAL), |
// and we need to adjust our monitor window |
if (!EqualRect(&gActiveVideoRect, &newActiveVideoRect)) |
{ |
if (gFullSize) |
{ |
width = newActiveVideoRect.right - newActiveVideoRect.left; |
height = newActiveVideoRect.bottom - newActiveVideoRect.top; |
gActiveVideoRect = newActiveVideoRect; |
SizeWindow(gMonitor, width, height, false); |
result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect)); |
} |
else if (gHalfSize) |
{ |
width = (newActiveVideoRect.right - newActiveVideoRect.left) / 2; |
height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 2; |
gActiveVideoRect = newActiveVideoRect; |
SizeWindow(gMonitor, width, height, false); |
result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect)); |
} |
else if (gQuarterSize) |
{ |
width = (newActiveVideoRect.right - newActiveVideoRect.left) / 4; |
height = (newActiveVideoRect.bottom - newActiveVideoRect.top) / 4; |
gActiveVideoRect = newActiveVideoRect; |
SizeWindow(gMonitor, width, height, false); |
result = SGSetChannelBounds(gVideoChannel, &(gMonitor->portRect)); |
} |
} |
// Has our crop changed? |
// This code shows how to be crop video panel friendly |
// Two important things - |
// 1) Be aware that you might have been cropped and adjust your |
// video window appropriately |
// 2) Be aware that you might have been adjusted and attempt to |
// account for this. Adjusting refers to using the digitizer |
// rect to "adjust" the active source rect within the maximum |
// source rect. This is useful if you're getting those nasty |
// black bands on the sides of your video display - you can use |
// the control-arrow key sequence to shift the active source |
// rect around when you're in the crop video panel |
adjustedActiveVideoRect = gActiveVideoRect; |
if (!EqualRect(&curVideoRect, &newVideoRect)) |
{ |
if ((newVideoRect.left < gActiveVideoRect.left) || (newVideoRect.right > gActiveVideoRect.right) || (newVideoRect.top < gActiveVideoRect.top) || (newVideoRect.bottom > gActiveVideoRect.bottom)) |
{ |
if (newVideoRect.left < gActiveVideoRect.left) |
{ |
adjustedActiveVideoRect.left = newVideoRect.left; |
adjustedActiveVideoRect.right -= (gActiveVideoRect.left - newVideoRect.left); |
} |
if (newVideoRect.right > gActiveVideoRect.right) |
{ |
adjustedActiveVideoRect.right = newVideoRect.right; |
adjustedActiveVideoRect.left += (newVideoRect.right - gActiveVideoRect.right); |
} |
if (newVideoRect.top < gActiveVideoRect.top) |
{ |
adjustedActiveVideoRect.top = newVideoRect.top; |
adjustedActiveVideoRect.bottom -= (gActiveVideoRect.top - newVideoRect.top); |
} |
if (newVideoRect.bottom > gActiveVideoRect.bottom) |
{ |
adjustedActiveVideoRect.bottom = newVideoRect.bottom; |
adjustedActiveVideoRect.top += (newVideoRect.bottom - gActiveVideoRect.bottom); |
} |
newBounds = newVideoRect; |
MapRect(&newBounds, &adjustedActiveVideoRect, &(gMonitor->portRect)); |
} |
else // Can't tell if we've been adjusted (digitizer rect is smaller on all sides |
// than the active source rect) |
{ |
newBounds = newVideoRect; |
MapRect(&newBounds, &gActiveVideoRect, &(gMonitor->portRect)); |
} |
width = newBounds.right - newBounds.left; |
height = newBounds.bottom - newBounds.top; |
result = SGSetChannelBounds(gVideoChannel, &newBounds); |
} |
// Clean out the part of the port that isn't being drawn in |
deadRgn = NewRgn(); |
if (deadRgn != nil) |
{ |
result = SGGetChannelBounds(gVideoChannel, &boundsRect); |
result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn); |
EraseRgn(deadRgn); |
DisposeRgn(deadRgn); |
} |
SetPort(savedPort); |
// The pause that refreshes |
result = SGPause(gSeqGrabber, false); |
} |
break; |
} |
case kSoundSettingsItem: |
{ |
if ((gSeqGrabber != 0L) && (gSoundChannel != 0L)) |
{ |
// Do the dialog thang |
result = SGSettingsDialog(gSeqGrabber, gSoundChannel, 0, nil, 0L, SeqGrabberModalFilterProc, (long)StripAddress((Ptr)gMonitor)); |
} |
break; |
} |
case kQuarterSizeItem: |
{ |
// New width and height |
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 4; |
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 4; |
// Set flags and menus |
gQuarterSize = true; |
gHalfSize = false; |
gFullSize = false; |
AdjustMenus(); |
// Resize the monitor |
GetPort(&savedPort); |
SetPort(gMonitor); |
result = SGPause(gSeqGrabber, true); |
result = SGGetChannelBounds(gVideoChannel, &curBounds); |
maxBoundsRect = gMonitor->portRect; |
SizeWindow(gMonitor, width, height, false); |
MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect)); |
result = SGSetChannelBounds(gVideoChannel, &curBounds); |
// Clean out part of port we're not drawing in |
deadRgn = NewRgn(); |
if (deadRgn != nil) |
{ |
result = SGGetChannelBounds(gVideoChannel, &boundsRect); |
result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn); |
EraseRgn(deadRgn); |
DisposeRgn(deadRgn); |
} |
SetPort(savedPort); |
result = SGPause(gSeqGrabber, false); |
break; |
} |
case kHalfSizeItem: |
{ |
// New width and height |
width = (gActiveVideoRect.right - gActiveVideoRect.left) / 2; |
height = (gActiveVideoRect.bottom - gActiveVideoRect.top) / 2; |
// Set flags and menus |
gQuarterSize = false; |
gHalfSize = true; |
gFullSize = false; |
AdjustMenus(); |
// Resize the monitor |
GetPort(&savedPort); |
SetPort(gMonitor); |
result = SGPause(gSeqGrabber, true); |
result = SGGetChannelBounds(gVideoChannel, &curBounds); |
maxBoundsRect = gMonitor->portRect; |
SizeWindow(gMonitor, width, height, false); |
MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect)); |
result = SGSetChannelBounds(gVideoChannel, &curBounds); |
// Clean out part of port we're not drawing in |
deadRgn = NewRgn(); |
if (deadRgn != nil) |
{ |
result = SGGetChannelBounds(gVideoChannel, &boundsRect); |
result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn); |
EraseRgn(deadRgn); |
DisposeRgn(deadRgn); |
} |
SetPort(savedPort); |
result = SGPause(gSeqGrabber, false); |
break; |
} |
case kFullSizeItem: |
{ |
// New width and height |
width = gActiveVideoRect.right - gActiveVideoRect.left; |
height = gActiveVideoRect.bottom - gActiveVideoRect.top; |
// Set flags and menus |
gQuarterSize = false; |
gHalfSize = false; |
gFullSize = true; |
AdjustMenus(); |
// Resize the monitor |
GetPort(&savedPort); |
SetPort(gMonitor); |
result = SGPause(gSeqGrabber, true); |
result = SGGetChannelBounds(gVideoChannel, &curBounds); |
maxBoundsRect = gMonitor->portRect; |
SizeWindow(gMonitor, width, height, false); |
MapRect(&curBounds, &maxBoundsRect, &(gMonitor->portRect)); |
result = SGSetChannelBounds(gVideoChannel, &curBounds); |
// Clean out part of port we're not drawing in |
deadRgn = NewRgn(); |
if (deadRgn != nil) |
{ |
result = SGGetChannelBounds(gVideoChannel, &boundsRect); |
result = XorRectToRgn(&boundsRect, &(gMonitor->portRect), &deadRgn); |
EraseRgn(deadRgn); |
DisposeRgn(deadRgn); |
} |
SetPort(savedPort); |
result = SGPause(gSeqGrabber, false); |
break; |
} |
default: |
{ |
break; |
} |
} |
} |
default: |
{ |
break; |
} |
} |
} |
//----------------------------------------------------------------------- |
static void DoAboutDialog(void) |
{ |
short itemHit; |
short itemType; |
Handle itemHandle; |
Rect itemRect; |
DialogPtr aboutDialog = GetNewDialog(kAboutDLOGID, nil, (WindowPtr) - 1L); |
// Do the boring about dialog |
GetDItem(aboutDialog, kAboutOKButtonOutline, &itemType, &itemHandle, &itemRect); |
SetDItem(aboutDialog, kAboutOKButtonOutline, itemType, (Handle)AboutDrawProc, &itemRect); |
ShowWindow(aboutDialog); |
do |
{ |
ModalDialog(nil, &itemHit); |
} while (itemHit != kAboutOKButton); |
DisposDialog(aboutDialog); |
} |
//----------------------------------------------------------------------- |
pascal void AboutDrawProc(DialogPtr theDialog, |
short theItemNum) |
{ |
PenState thePenState; |
OSErr result = noErr; |
Rect itemRect; |
Handle itemHandle; |
short itemType; |
// Set up the pen |
GetPenState(&thePenState); |
GetDItem(theDialog, theItemNum, &itemType, &itemHandle, &itemRect); |
// What item do we need to draw? |
switch (theItemNum) |
{ |
case kAboutOKButtonOutline: |
PenNormal(); |
PenMode(patCopy); |
PenSize(3, 3); |
InsetRect(&itemRect, -4, -4); |
FrameRoundRect(&itemRect, 16, 16); |
break; |
default: |
break; |
} |
// Restore the pen |
SetPenState(&thePenState); |
} |
//----------------------------------------------------------------------- |
static OSErr XorRectToRgn(Rect* srcRectA, |
Rect* srcRectB, |
RgnHandle* destRgn) |
{ |
RgnHandle srcRgnA = NewRgn(); |
RgnHandle srcRgnB = NewRgn(); |
OSErr result = noErr; |
if ((destRgn != nil) && (*destRgn != nil)) |
{ |
if ((srcRgnA != nil) && (srcRgnB != nil)) |
{ |
RectRgn(srcRgnA, srcRectA); |
RectRgn(srcRgnB, srcRectB); |
XorRgn(srcRgnA, srcRgnB, *destRgn); |
} |
else |
{ |
result = memFullErr; |
} |
} |
else |
{ |
result = nilHandleErr; |
} |
return (result); |
} |
//----------------------------------------------------------------------- |
pascal Boolean SeqGrabberModalFilterProc(DialogPtr theDialog, |
EventRecord* theEvent, |
short* itemHit, |
long refCon) |
{ |
// Ordinarily, if we had multiple windows we cared about, we'd handle |
// updating them in here, but since we don't, we'll just clear out |
// any update events meant for us |
Boolean handled = false; |
if ((theEvent->what == updateEvt) && ((WindowPtr)theEvent->message == (WindowPtr)refCon)) |
{ |
BeginUpdate((WindowPtr)refCon); |
EndUpdate((WindowPtr)refCon); |
handled = true; |
} |
return (handled); |
} |
//----------------------------------------------------------------------- |
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(); |
} |
//----------------------------------------------------------------------- |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14