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.
VDTextSample.c
/* |
File: VDTextSample.c |
Written by: Larry Lai, DTS |
Copyright: © 1995 by Apple Computer, Inc., all rights reserved. |
This snippet shows you how to draw and erase text to the video |
preview image without causing flickers on the screen. It only |
works with 'vdig's that support key color (Quadra 660AV, 840AV, |
630 and PowerMac 6100/7100/8100 AVs). Read "Inside Macintosh: |
QuickTime Component" Video Digitizer Component chapter for more |
information. |
Change History (most recent first): |
<1> 2/22/95 LL create first working version. |
3/10/95 LL add about-this-app box. |
To Do: |
*/ |
/* HEADER FILES */ |
#include <Types.h> |
#include <Memory.h> |
#include <QuickDraw.h> |
#include <Palettes.h> |
#include <QDOffscreen.h> |
#include <Errors.h> |
#include <Fonts.h> |
#include <Dialogs.h> |
#include <Windows.h> |
#include <Menus.h> |
#include <Events.h> |
#include <OSUtils.h> |
#include <Resources.h> |
#include <ToolUtils.h> |
#include <AppleEvents.h> |
#include <GestaltEqu.h> |
#include <Processes.h> |
#include <Aliases.h> |
#include <MixedMode.h> |
#include <LowMem.h> |
#include <Sound.h> |
#include <Movies.h> |
#include <QuickTimeComponents.h> |
#include <ImageCompression.h> |
/* DEFINES */ |
#define appleID 128 |
#define appleMenu 0 |
#define aboutMeCommand 1 |
#define fileID 129 |
#define textCommand 1 |
#define quitCommand 3 |
#define aboutMeDLOG 128 |
#define okButton 1 |
#define kSoundID 128 |
#define kBruceIconItem 4 |
/* FUNCTION PROTOTYPES*/ |
void CheckError(OSErr error, Str255 displayString); |
Boolean IsQuickTimeInstalled(void); |
void initialize(void); |
WindowPtr makeWindow(void); |
SeqGrabComponent makeSequenceGrabber (WindowPtr aWindow); |
void makeGrabChannels ( SeqGrabComponent anSG, |
SGChannel *videoChannel, |
SGChannel *soundChannel, |
const Rect *bounds, Boolean willRecord); |
void EraseVideo(SeqGrabComponent aSG, WindowPtr aWindow, SGChannel theChannel); |
void ShowAboutMeDialog(void); |
void DoCommand(long mResult); |
pascal Boolean MyFilter(DialogPtr inputDialog, EventRecord *myDialogEvent, short *theDialogItem); |
/* GLOBALS */ |
Boolean done = false; |
Boolean showString = true; |
Boolean menuKey = false; |
MenuHandle mymenu0, mymenu1; |
WindowPtr theWindow; |
SeqGrabComponent theSG; |
SGChannel videoChannel, soundChannel; |
/* FUNCTIONS */ |
void CheckError(OSErr error, Str255 displayString) |
{ |
if(error == noErr) return; |
if(displayString[0] > 0) |
DebugStr(displayString); |
ExitToShell(); |
} |
Boolean IsQuickTimeInstalled(void) |
{ |
short error; |
long result; |
error = Gestalt(gestaltQuickTime, &result); |
return (error == noErr); |
} |
void ShowAboutMeDialog(void) |
{ |
GrafPtr savePort; |
DialogPtr theDialog; |
Handle theSound; |
short itemHit; |
GetPort(&savePort); |
theDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) - 1); |
SetPort(theDialog); |
do |
{ |
ModalDialog((ModalFilterProcPtr) MyFilter, &itemHit); |
switch(itemHit){ |
case kBruceIconItem: |
/* don't mess with Bruce */ |
theSound = GetResource('snd ', kSoundID); |
if (theSound != nil) { |
SndPlay(nil, (SndListHandle)theSound, false); |
ReleaseResource(theSound); |
} |
break; |
} |
} while (itemHit != okButton); |
CloseDialog(theDialog); |
SetPort(savePort); |
return; |
} |
// True confession: this was stolen from C.K's "DialogBits.c". |
pascal Boolean MyFilter(DialogPtr inputDialog, EventRecord *myDialogEvent, short *theDialogItem) |
{ |
Rect tempRect; |
short tempItem; |
Handle tempHandle; |
Point tempPoint; |
Point mousePoint; |
Boolean hiLit = false; |
Boolean returnVal = false; |
if (myDialogEvent->what == mouseDown) { |
mousePoint = (myDialogEvent->where); |
GlobalToLocal(&mousePoint); |
/* First see if we're in Bruce */ |
GetDItem(inputDialog, kBruceIconItem, &tempItem, &tempHandle, &tempRect); |
if (PtInRect(mousePoint, &tempRect)) { |
/* invert my icon, and track it whilst the user holds the mouse down */ |
InvertRect(&tempRect); |
hiLit = true; |
while (StillDown()) { |
GetMouse(&tempPoint); /* returns point in local coords */ |
if (PtInRect(tempPoint, &tempRect)) { |
/* in the rect. See if it's hilighted or not */ |
if (hiLit == false) { |
hiLit = true; |
InvertRect(&tempRect); |
} |
} else { |
/* not in the rectangle. If it's hilit, get rid of that */ |
if (hiLit == true) { |
hiLit = false; |
InvertRect(&tempRect); |
} |
} |
} |
if (hiLit == true) { |
/* if it's still hilited when the mouse comes up, then that means the */ |
/* user stayed in and wants to take this icon action */ |
InvertRect(&tempRect); /* clear the hiliting if it's still lit */ |
*theDialogItem = kBruceIconItem; |
returnVal = true; /* telling the Dialog Manager we handled it, pass item back */ |
} |
} |
} |
return returnVal; |
} |
void initialize(void) |
{ |
OSErr err; |
short i; |
InitGraf (&qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(nil); |
MaxApplZone(); |
for (i = 0; i<=10; i++) |
MoreMasters(); |
if(!IsQuickTimeInstalled()) |
CheckError(-1, "\pPlease install QuickTime and try again."); |
err = EnterMovies(); |
CheckError(err, "\pUnable to initialize Movie Toolbox."); |
/* Set up menus. */ |
mymenu0 = GetMenu(appleID); |
AddResMenu(mymenu0, 'DRVR'); |
InsertMenu(mymenu0, 0); |
mymenu1 = GetMenu(fileID); |
InsertMenu(mymenu1, 0); |
DrawMenuBar(); |
} |
WindowPtr makeWindow(void) |
{ |
WindowPtr aWindow; |
Rect windowRect = {0, 0, 240, 320}; |
Rect bestRect; |
/* figure out the best monitor for the window */ |
GetBestDeviceRect (nil, &bestRect); |
/* put the window in the top left corner of that monitor */ |
OffsetRect(&windowRect, bestRect.left + 10, bestRect.top + 50); |
/* create the window */ |
aWindow = NewCWindow(nil, &windowRect, "\pPreviewer", |
true, noGrowDocProc, (WindowPtr)-1, |
true, 0); |
/* and set the port to the new window */ |
SetPort(aWindow); |
return aWindow; |
} |
main (void) |
{ |
OSErr err = noErr; |
char key; |
initialize(); |
theWindow = makeWindow(); |
theSG = makeSequenceGrabber(theWindow); |
if(!theSG) return; |
makeGrabChannels(theSG, &videoChannel, &soundChannel, |
&theWindow->portRect, false); |
if((videoChannel == nil) && (soundChannel == nil)) |
CheckError(err, "\pCan't start preview"); |
err = SGStartPreview(theSG); |
CheckError(err, "\pCan't start preview"); |
while(!done) { |
ICMAlignmentProcRecord alignProc; |
short part; |
WindowPtr whichWindow; |
EventRecord theEvent; |
GetNextEvent(everyEvent, &theEvent); |
switch(theEvent.what) { |
case nullEvent: /*give the sequence grabber time */ |
err = SGIdle (theSG); |
if(err ) done = true; |
break; |
case updateEvt: |
if(theEvent.message == (long) theWindow) { |
/* inform the sequesnce grabber of the update */ |
SGUpdate(theSG, nil); |
EraseVideo(theSG, theWindow, videoChannel); |
BeginUpdate(theWindow); |
EndUpdate(theWindow); |
/*and swallow the update event */ |
} |
break; |
case mouseDown: |
part = FindWindow(theEvent.where, |
&whichWindow); |
switch(part) { |
case inSysWindow: |
SystemClick(&theEvent, whichWindow); |
break; |
case inMenuBar: |
DoCommand(MenuSelect(theEvent.where)); |
case inContent: |
/* pause until mouse button is released */ |
SGPause(theSG, true); |
while (StillDown()) |
; |
SGPause(theSG, false); |
EraseVideo(theSG, theWindow, videoChannel); |
break; |
case inGoAway: |
done = TrackGoAway (theWindow, theEvent.where); |
break; |
case inDrag: |
/*pause when dragging window so video doesn't draw in |
the wrong place */ |
SGPause (theSG, true); |
SGGetAlignmentProc(theSG, &alignProc); |
DragAlignedWindow(theWindow, |
theEvent.where, |
&qd.screenBits.bounds, |
nil, &alignProc); |
SGPause(theSG, false); |
EraseVideo(theSG, theWindow, videoChannel); |
break; |
} |
break; |
case keyDown: |
case autoKey: |
key = theEvent.message & charCodeMask; |
if (theEvent.modifiers & cmdKey) |
if (theEvent.what == keyDown) |
DoCommand(MenuKey(key)); |
break; |
} |
} |
/*clean up*/ |
SGStop (theSG); |
CloseComponent(theSG); |
DisposeWindow (theWindow); |
} |
void DoCommand(long mResult) |
{ |
int theMenu; |
short theItem; |
Str255 daName; |
GrafPtr saveThePort; |
theItem = LoWord(mResult); |
theMenu = HiWord(mResult); |
switch (theMenu) |
{ |
case appleID: |
if (theItem == aboutMeCommand) |
ShowAboutMeDialog(); |
else |
{ |
GetMenuItemText(mymenu0, theItem, daName); |
GetPort(&saveThePort); |
(void)OpenDeskAcc(daName); |
SetPort(saveThePort); |
} |
break; |
case fileID: |
switch (theItem) |
{ |
case textCommand: |
showString = 1 - showString; |
menuKey = true; |
EraseVideo(theSG, theWindow, videoChannel); |
break; |
case quitCommand: |
done = true; |
break; |
default: |
break; |
} |
break; |
} |
HiliteMenu(0); |
return; |
} |
SeqGrabComponent makeSequenceGrabber (WindowPtr aWindow) |
{ |
SeqGrabComponent anSG; |
OSErr err = noErr; |
/* open up the default sequence grabber */ |
anSG = OpenDefaultComponent (SeqGrabComponentType, 0); |
if (anSG) { |
/* initialize the default sequence grabber component */ |
err = SGInitialize(anSG); |
if (!err ) { |
/* set the sequence grabber's graphics world to the |
specified window */ |
err = SGSetGWorld (anSG, (CGrafPtr) aWindow, nil); |
} |
} |
if (err && anSG) { |
/* clean up on failure */ |
CloseComponent(anSG); |
anSG = nil; |
} |
return anSG; |
} |
void makeGrabChannels (SeqGrabComponent anSG, |
SGChannel *videoChannel, |
SGChannel *soundChannel, |
const Rect *bounds, Boolean willRecord) |
{ |
OSErr err; |
long usage; |
/*figure out th usage */ |
usage = seqGrabPreview; |
if(willRecord) |
usage |= seqGrabRecord; |
/* create a video channel */ |
err = SGNewChannel (anSG, VideoMediaType, videoChannel); |
if(!err) { |
/* set boundries for new video channel */ |
err = SGSetChannelBounds (*videoChannel, bounds); |
/*set usage for new video channel */ |
if(!err) |
err = SGSetChannelUsage (*videoChannel, |
usage | seqGrabPlayDuringRecord); |
if(err) { |
/* clean up on failure */ |
SGDisposeChannel(anSG, *videoChannel); |
*videoChannel = nil; |
} |
} |
/* create a sound channel */ |
err = SGNewChannel (anSG, SoundMediaType, soundChannel); |
if(!err){ |
/*set usage of new sound channel */ |
err = SGSetChannelUsage (*soundChannel, usage); |
if(err){ |
/* clean up on failure */ |
SGDisposeChannel(anSG, *soundChannel); |
*soundChannel = nil; |
} |
} |
} |
void EraseVideo(SeqGrabComponent aSG, WindowPtr aWindow, SGChannel theChannel) |
{ |
GrafPtr savePort; |
GDHandle saveGD; |
RGBColor oldColor, rgb, myRGBColor; |
VideoDigitizerComponent aVDIG; |
long index; |
OSErr error; |
aVDIG = SGGetVideoDigitizerComponent(theChannel); |
error = VDGetKeyColor(aVDIG, &index); |
if(error == noErr){ |
/* yellow is the color for the text on display */ |
myRGBColor.red = 0xFC00; |
myRGBColor.green = 0xF37D; |
myRGBColor.blue = 0x052F; |
GetPort(&savePort); |
saveGD = GetGDevice(); |
SetGDevice(GetMainDevice()); |
SetPort(aWindow); |
if(!showString && menuKey){ |
Index2Color(index, &rgb); |
GetForeColor(&oldColor); |
RGBForeColor(&rgb); |
PaintRect(&((GrafPtr) aWindow)->portRect); |
RGBForeColor(&oldColor); |
menuKey = false; |
} |
if(showString){ |
MoveTo (30,30); |
TextFont (applFont); |
TextSize (14); |
RGBForeColor(&myRGBColor); |
DrawString("\pCupertino News"); |
} |
SetPort(savePort); |
SetGDevice(saveGD); |
} |
else |
{ |
/* can not find the key color, let's us bail */ |
SysBeep(10); |
Alert(129, nil); |
done = true; |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14