home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QuickTime 2.0 Developer Kit
/
QuickTime 2.0 Developer Kit.iso
/
mac
/
MAC
/
Programming Stuff
/
Sample Code
/
Movie Toolbox
/
MovieBrowser
/
MovieBrowser.c
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1994-12-11
|
29.8 KB
|
1,339 lines
|
[
TEXT/MPS
]
/*
File: MovieBrowser.c
Written by: Peter Hoddie
Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<1> 12/8/94 khs changed the format of the file to the new look and feel
*/
// INCLUDES
#include <Aliases.h>
#include <AppleEvents.h>
#include <Dialogs.h>
#include <Errors.h>
#include <Events.h>
#include <Memory.h>
#include <Movies.h>
#include <ToolUtils.h>
#include <LowMem.h>
#include <SegLoad.h>
#include <Fonts.h>
#include <GestaltEqu.h>
#include <Devices.h>
#include <Resources.h>
// STRUCTURES
typedef struct Document {
WindowPtr w;
Movie m;
MovieController mc;
short page;
short pageCount;
short curResID;
short resRef;
Track firstTextTrack;
FSSpec fss;
Rect movieArea;
Rect scrollArea;
Boolean noButtons;
Boolean showController;
Rect sprocketsRectTop;
Rect sprocketsRectBottom;
Rect scrollAndSprocketsArea;
long scrollOffset;
long scrollPhaseShift;
RGBColor backgroundColor;
Rect thumbnailSize;
TimeValue **lastMovieTime;
Handle names;
PicHandle titleBackground;
Rect titleRect;
Rect titleArea;
Str255 movieName;
Point titlePlace;
short lastPageClick;
unsigned long lastPageClickTime;
} Document, *DocumentPtr;
typedef long (*DocFunction)(DocumentPtr d, void *refCon);
// FUNCTION PROTOTYPES
void doAnAlert(StringPtr s, short err);
void colorMenus(void);
Boolean doMenuItem(long selection);
void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime);
DocumentPtr OpenDocument(FSSpec *fss);
void CloseDocument(DocumentPtr d);
void GoToPage(DocumentPtr d, short pageNum);
DocumentPtr GetWindowDocument(WindowPtr w);
long ForEachDocument(DocFunction df, void *refCon);
long TestOneEvent(DocumentPtr d, EventRecord *e);
long IdleOneDocument(DocumentPtr d, void *refCon);
PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds);
void GetScrollArea(DocumentPtr d, Rect *bounds);
void ActivateDocument(DocumentPtr d);
void UpdateDocument(DocumentPtr d);
void OpenFinderDocs(void);
OSErr MissedAEParameters (AppleEvent *message);
pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon);
pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon);
// GLOBALS
short gAppResFile;
Boolean gDone = false;
GWorldPtr gSprockets = 0;
Str255 gLastSearchText;
unsigned long gLastWNETime;
Boolean gInBackground = false;
long gSysVersion = 0;
// DEFINES
// don't give the system too much time...
#define kWNEInterval (90)
#define kBetweenThumbSize (2)
// FUNCTIONS
void doAnAlert(StringPtr s, short err)
{
Str31 s1;
NumToString(err, s1);
ParamText(s, err ? s1 : 0, 0, 0);
Alert(128, 0);
}
void colorMenus(void)
{
MenuHandle mh;
short count, i;
DocumentPtr d = GetWindowDocument(FrontWindow());
mh = GetMHandle(129);
DisableItem(mh, 2);
if (FrontWindow()) EnableItem(mh, 2);
mh = GetMHandle(130);
count = CountMItems(mh);
for (i = 1; i <= count; i++)
CheckItem(mh, i, d && (i == (d->page + 1)));
mh = GetMHandle(131);
DisableItem(mh, 1);
DisableItem(mh, 3);
DisableItem(mh, 4);
DisableItem(mh, 5);
DisableItem(mh, 6);
DisableItem(mh, 8);
DisableItem(mh, 9);
DisableItem(mh, 11);
if (d) {
if (d->firstTextTrack) {
EnableItem(mh, 8);
if (gLastSearchText[0])
EnableItem(mh, 9);
}
if (d->m)
EnableItem(mh, 4);
EnableItem(mh, 11);
CheckItem(mh, 11, d->showController);
}
}
Boolean doMenuItem(long selection)
{
short menu = HiWord(selection);
short item = LoWord(selection);
Boolean done = false;
DocumentPtr d = GetWindowDocument(FrontWindow());
switch (menu) {
case 128:
if (item > 2) {
Str255 daName;
GetItem(GetMHandle(128), item, daName);
OpenDeskAcc(daName);
}
else {
short item = 0;
short saveRes = CurResFile();
DialogPtr d;
short kind;
Handle h;
Rect r;
UseResFile(gAppResFile);
d = GetNewDialog(129, nil, (WindowPtr)-1);
SetPort(d);
GetDItem(d, 1, &kind, &h, &r);
PenSize(3,3);
InsetRect(&r,-4,-4);
FrameRoundRect(&r,16,16);
while (d && (item != 1))
ModalDialog(nil, &item);
UseResFile(saveRes);
if (d) DisposDialog(d);
}
break;
case 129:
switch (item) {
case 1: {
StandardFileReply reply;
OSType docType = 'Dalí';
StandardGetFilePreview(nil, 1, &docType, &reply);
if (reply.sfGood)
OpenDocument(&reply.sfFile);
}
break;
case 2: CloseDocument(d);
break;
case 4: done = true;
break;
}
break;
case 130:
GoToPage(GetWindowDocument(FrontWindow()), item - 1);
break;
case 131:
switch (item) {
case 4: if (d && d->m)
PutMovieOnScrap(d->m, DoTheRightThing);
break;
case 8: {
DialogPtr dlg = GetNewDialog(130, nil, (WindowPtr)-1);
short kind;
Handle h;
Rect r;
short item = 0;
Str255 str;
ModalFilterProcPtr filter = nil;
if (!dlg) break;
// set up some dialog manager slime if not System 7
if (gSysVersion < 7 ) {
SetDialogDefaultItem(dlg, 1);
SetDialogCancelItem(dlg, 2);
SetDialogTracksCursor(dlg, true);
GetStdFilterProc(&filter);
}
GetDItem(dlg, 4, &kind, &h, &r);
SetIText(h, gLastSearchText);
SelIText(dlg, 4, 0, 32767);
while ((item != 1) && (item != 2))
ModalDialog(filter, &item);
GetIText(h, str);
DisposDialog(dlg);
if (item == 1 && str[0]) {
BlockMove(str, gLastSearchText, sizeof(gLastSearchText));
goto doSearch;
}
break;
}
case 9: {
TimeValue newTime;
OSErr err;
MediaHandler textHandler;
long textOffset;
doSearch:
// text media handler really wants lower case letters, so make sure it gets 'em
if (gSysVersion >= 7)
LowerText((Ptr)&gLastSearchText[1], gLastSearchText[0]);
else {
short i = 0;
while (i++ <= gLastSearchText[0]) {
char c = gLastSearchText[i];
if ((c >= 'A') && (c <= 'Z'))
gLastSearchText[i] -= 32;
}
}
textHandler = GetMediaHandler(GetTrackMedia(d->firstTextTrack));
err = FindNextText(textHandler, (Ptr)&gLastSearchText[1], gLastSearchText[0],
findTextWrapAround, GetMovieTime(d->m, nil),
&newTime, nil, &textOffset);
if (!err && (newTime != -1)) {
TimeRecord tr;
RGBColor rgb;
tr.value.lo = newTime;
tr.value.hi = 0;
tr.scale = GetMovieTimeScale(d->m);
tr.base = 0;
MCDoAction(d->mc, mcActionGoToTime, &tr);
rgb = (**((GrafVars **)((CGrafPtr)d->w)->grafVars)).rgbHiliteColor;
HiliteTextSample(textHandler, newTime, textOffset,
textOffset + gLastSearchText[0], &rgb);
}
else
SysBeep(1);
}
break;
case 11: {
d->showController = !d->showController;
MCSetVisible(d->mc, d->showController);
break;
}
break;
}
}
HiliteMenu(0);
return done;
}
DocumentPtr OpenDocument(FSSpec *fss)
{
OSErr err;
DocumentPtr d;
Rect r;
Point center;
short resID;
Handle h;
d = (DocumentPtr)NewPtrClear(sizeof(Document));
err = MemError();
if (err != noErr) goto bail;
d->fss = *fss;
d->resRef = FSpOpenResFile(fss, fsRdPerm);
if ((d->resRef == -1) || ResError()) {
err = resNotFound;
d->resRef = 0;
goto bail;
}
d->lastPageClick = -1;
d->names = NewHandle(0);
// count the pages, and rememeber their names
resID = 128;
SetResLoad(false);
do {
Handle r;
short id;
OSType rt;
Str255 name;
r = Get1Resource(rAliasType, resID++);
if (r != NULL)
d->pageCount++;
else
break;
// remember the name
GetResInfo(r, &id, &rt, name);
PtrAndHand(name, d->names, name[0] + 1);
err = MemError();
if (err != noErr) goto bail;
} while (true);
SetResLoad(true);
// make the window
d->w = GetNewCWindow(128, nil, (WindowPtr)-1);
if (!d->w) {
err = memFullErr;
goto bail;
}
SetWTitle(d->w, fss->name);
TextFont(GetSysFont());
// get back color
h = Get1Resource('RGB ', 128);
if (h != NULL) {
d->backgroundColor = **(RGBColor **)h;
ReleaseResource(h);
}
else {
short saveRes = CurResFile();
UseResFile(gAppResFile);
d->backgroundColor = **(RGBColor **)Get1Resource('RGB ', 128);
UseResFile(saveRes);
}
// pick up first thumbnail pict for measurement
h = Get1Resource('PICT', 128);
if (!h) {
err = resNotFound;
goto bail;
}
d->thumbnailSize = (**(PicHandle)h).picFrame;
OffsetRect(&d->thumbnailSize, -d->thumbnailSize.left, -d->thumbnailSize.top);
d->thumbnailSize.right += kBetweenThumbSize;
// show a controller?
d->showController = false;
h = Get1Resource('MCmc', 128);
if (h) {
d->showController = **h;
ReleaseResource(h);
}
// make page time table
d->lastMovieTime = (TimeValue **)NewHandleClear(d->pageCount * sizeof(TimeValue));
err = MemError();
if (err != noErr) goto bail;
d->movieArea = **(Rect **)GetResource('RECT', 128);
ReleaseResource(GetResource('RECT', 128));
OffsetRect(&d->movieArea, -d->movieArea.left, -d->movieArea.top);
// figure out what to use for title background
d->titleBackground = (PicHandle)Get1Resource('PICT', 1048);
if (!d->titleBackground) {
short saveRes = CurResFile();
UseResFile(gAppResFile);
d->titleBackground = (PicHandle)GetPicture(1048);
UseResFile(saveRes);
}
LoadResource((Handle)d->titleBackground);
r = (**d->titleBackground).picFrame;
OffsetRect(&r, -r.left, -r.top);
OffsetRect(&r, (d->movieArea.right / 2) - (r.right / 2), 0);
d->titleRect = r;
OffsetRect(&d->titleRect, 0, (d->titleRect.bottom - d->titleRect.top) / 3);
InsetRect(&r, 0, -((d->titleRect.bottom - d->titleRect.top) / 3));
d->titleArea = r;
OffsetRect(&d->movieArea, 0, d->titleArea.bottom);
SizeWindow(d->w, d->movieArea.right,
d->movieArea.bottom + d->thumbnailSize.bottom + (gSprockets->portRect.bottom * 2), false);
// figure out how to keep things centered
GetScrollArea(d, &r);
d->scrollArea = r;
OffsetRect(&r, -r.left, -r.top);
d->scrollPhaseShift = (d->thumbnailSize.right) - (r.right % d->thumbnailSize.right)/2;
// calculate sprockets rect
d->sprocketsRectTop = d->scrollArea;
d->sprocketsRectTop.bottom = d->scrollArea.top;
d->sprocketsRectTop.top -= gSprockets->portRect.bottom;
d->sprocketsRectBottom = d->scrollArea;
d->sprocketsRectBottom.top = d->scrollArea.bottom;
d->sprocketsRectBottom.bottom += gSprockets->portRect.bottom;
UnionRect(&d->scrollArea, &d->sprocketsRectTop, &d->scrollAndSprocketsArea);
UnionRect(&d->sprocketsRectBottom, &d->scrollAndSprocketsArea, &d->scrollAndSprocketsArea);
SetWRefCon(d->w, (long)d);
SetPort(d->w);
r = d->w->portRect;
GetBestDeviceRect(nil, &r);
if (r.top == 0) r.top += GetMBarHeight();
center.h = (r.left + r.right) >> 1;
center.v = (r.top + r.bottom) >> 1;
r.left = center.h - (d->w->portRect.right >> 1);
r.right = r.left + d->w->portRect.right;
r.top = center.v - (d->w->portRect.bottom >> 1);
r.bottom = r.top + d->w->portRect.bottom;
MoveWindow(d->w, r.left, r.top, false);
AlignWindow(d->w, false, &d->movieArea, nil);
ShowWindow(d->w);
GoToPage(d, d->page);
bail:
if (err) CloseDocument(d);
return d;
}
void CloseDocument(DocumentPtr d)
{
if (!d) return;
if (d->resRef) CloseResFile(d->resRef);
if (d->mc) DisposeMovieController(d->mc);
if (d->lastMovieTime) DisposHandle((Handle)d->lastMovieTime);
if (d->names) DisposHandle(d->names);
DisposeMovie(d->m);
if (d->w) DisposeWindow(d->w);
DisposPtr((Ptr)d);
ActivateDocument(0); // clear out the movies menu
}
DocumentPtr GetWindowDocument(WindowPtr w)
{
if (!w) return nil;
if (((WindowPeek)w)->windowKind == userKind)
return (DocumentPtr)GetWRefCon(w);
else
return nil;
}
void GoToPage(DocumentPtr d, short pageNum)
{
OSErr err;
short resID;
Movie newMovie = nil;
Point where = {0,0};
Rect r;
short saveRes;
FSSpec movieFile;
Boolean whoCares;
short movieResRef;
AliasHandle alias;
RgnHandle rgn;
short trashID;
OSType trackType;
if (pageNum < 0)
pageNum = d->pageCount - 1;
else
pageNum = pageNum % d->pageCount;
resID = pageNum + 128;
if (resID == d->curResID) return;
// resolve alias to the file
saveRes = CurResFile();
UseResFile(d->resRef);
alias = (AliasHandle)Get1Resource(rAliasType, resID);
UseResFile(saveRes);
if (!alias) return;
err = ResolveAlias((gSysVersion >= 7) ? &d->fss : 0, alias, &movieFile, &whoCares);
GetResInfo((Handle)alias, &trashID, &trackType, d->movieName);
ReleaseResource((Handle)alias);
if (err) return;
// get the movie
SetCursor(*GetCursor(watchCursor));
OpenMovieFile(&movieFile, &movieResRef, fsRdPerm);
SetPort(d->w);
RGBBackColor(&d->backgroundColor); // for erasing
err = NewMovieFromFile(&newMovie, movieResRef, nil, nil,
newMovieActive, nil);
BackColor(whiteColor);
SetCursor(&qd.arrow);
CloseMovieFile(movieResRef);
if (err) return;
// position new movie a little
GetMovieBox(newMovie, &r);
OffsetRect(&r, -r.left, -r.top);
SetMovieBox(newMovie, &r);
// restore movie's previous time
SetMovieTimeValue(newMovie, (*d->lastMovieTime)[pageNum]);
// position movie in window
if (d->mc) {
TimeValue saveTime;
// invalidate the old one
rgn = MCGetWindowRgn(d->mc, d->w);
if (rgn) {
InvalRgn(rgn);
DisposeRgn(rgn);
}
// store the old movie's time
saveTime = GetMovieTime(d->m, nil);
(*d->lastMovieTime)[d->page] = saveTime;
SetMovieVolume(newMovie, GetMovieVolume(d->m)); // don't lose the volume setting
// change the movie on the controller
MCSetVisible(d->mc, false);
MCSetMovie(d->mc, newMovie, d->w, where);
MCPositionController(d->mc, &d->movieArea, nil, 0);
if (d->showController)
MCSetVisible(d->mc, true);
}
else {
// create a new controller
d->mc = NewMovieController(newMovie, &d->movieArea, d->showController ? 0 : mcNotVisible);
if (!d->mc) return;
MCDoAction(d->mc, mcActionSetKeysEnabled, (void *)true);
}
// update state
DisposeMovie(d->m);
d->m = newMovie;
d->curResID = resID;
d->page = pageNum;
// look for text
{
long trackCount, i;
d->firstTextTrack = nil;
trackCount = GetMovieTrackCount(d->m);
for (i=1; i<=trackCount; i++) {
Track t = GetMovieIndTrack(d->m, i);
OSType mediaType;
GetMediaHandlerDescription(GetTrackMedia(t), &mediaType, nil, nil);
if (mediaType == 'text') {
d->firstTextTrack = t;
break;
}
}
}
// invalidate the new one
rgn = MCGetWindowRgn(d->mc, d->w);
if (rgn) {
InvalRgn(rgn);
DisposeRgn(rgn);
}
// update the title variables
{
FontInfo fi;
short width;
InvalRect(&d->titleRect);
GetFontInfo(&fi);
width = StringWidth(d->movieName);
d->titlePlace.h = ((d->titleRect.right + d->titleRect.left) / 2) - (width / 2);
d->titlePlace.v = ((d->titleRect.top + d->titleRect.bottom) / 2) + (fi.ascent / 2);
}
}
void DoContentClick(DocumentPtr d, Point where, unsigned long clickTime)
{
Rect r;
short scrollValue = 0;
unsigned long lastTicks = TickCount();
long delayTime = 15;
Rect mustRect = d->w->portRect;
PicHandle showPict = nil, restorePict = nil;
if (!d) return;
SetPort(d->w);
GlobalToLocal(&where);
tryAgain:
// try left arrow
GetArrow(d, false, &r);
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
// go left
if (d->scrollOffset != 0)
d->scrollOffset--;
else
d->scrollOffset = d->pageCount - 1;
scrollValue = +1;
mustRect = r;
restorePict = GetPicture(1024);
showPict = GetPicture(1026);
d->lastPageClick = -1;
goto gotHit;
}
// try right arrow
GetArrow(d, true, &r);
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
// go right
if (d->scrollOffset != (d->pageCount - 1))
d->scrollOffset++;
else
d->scrollOffset = 0;
scrollValue = -1;
mustRect = r;
restorePict = GetPicture(1025);
showPict = GetPicture(1027);
goto gotHit;
}
r = d->scrollArea;
if (PtInRect(where, &r) && PtInRect(where, &mustRect)) {
// clicked on an image
short internalOffset = (where.h - r.left + d->scrollPhaseShift) / d->thumbnailSize.right;
Boolean wasIn, inRect;
Rect clipRect;
r = d->scrollArea;
ClipRect(&r);
clipRect = r;
r.right = r.left + d->thumbnailSize.right;
OffsetRect(&r, internalOffset * d->thumbnailSize.right, 0);
OffsetRect(&r, -d->scrollPhaseShift, 0);
PenMode(patXor);
PenPat((ConstPatternParam)&qd.gray);
PenSize(3, 3);
FrameRect(&r);
wasIn = true;
while (StillDown()) {
GetMouse(&where);
inRect = PtInRect(where, &r);
if (inRect != wasIn) {
FrameRect(&r);
wasIn = inRect;
}
ClipRect(&d->w->portRect);
ForEachDocument(IdleOneDocument, nil);
ClipRect(&clipRect);
}
if (wasIn) FrameRect(&r);
PenNormal();
ClipRect(&d->w->portRect);
if (wasIn) {
short newPage = (d->scrollOffset + internalOffset) % d->pageCount;
SInt32 dTime = LMGetDoubleTime();
if ( ( d->lastPageClick == newPage) &&
( (d->lastPageClickTime + dTime) >= clickTime)
) {
Fixed curRate;
MCDoAction(d->mc, mcActionGetPlayRate, &curRate);
if (!curRate) {
EventRecord whoCares;
TimeValue t = GetMovieTime(d->m, nil);
TimeValue movieDur = GetMovieDuration(d->m);
Fixed preferredRate = GetMoviePreferredRate(d->m);
if (t == movieDur) t = 0;
PrerollMovie(d->m, t, preferredRate);
EventAvail(0, &whoCares);
EventAvail(0, &whoCares);
EventAvail(0, &whoCares);
UpdateDocument(d);
MCIdle(d->mc);
MCIdle(d->mc);
MCIdle(d->mc);
MCDoAction(d->mc, mcActionPlay, (void *)preferredRate);
}
d->lastPageClick = -1;
d->lastPageClickTime += 500;
}
else {
if (newPage == d->page) {
MCDoAction(d->mc, mcActionPlay, (void *)0);
d->lastPageClick = newPage;
}
else {
GoToPage(d, newPage);
d->lastPageClick = newPage;
}
}
d->lastPageClickTime = clickTime;
}
r = mustRect;
goto gotHit;
}
gotHit:
if (scrollValue) {
Rect r;
RgnHandle rgn;
if (showPict) DrawPicture(showPict, &mustRect);
r = d->scrollArea;
rgn = NewRgn();
if (rgn != NULL) {
RGBBackColor(&d->backgroundColor);
ScrollRect(&r, d->thumbnailSize.right * scrollValue, 0, rgn);
BackColor(whiteColor);
InvalRgn(rgn);
DisposeRgn(rgn);
UpdateDocument(d);
ClipRect(&d->w->portRect);
do {
ForEachDocument(IdleOneDocument, nil);
} while (StillDown() && ((unsigned long)TickCount()) < (lastTicks + delayTime));
if (StillDown()) {
lastTicks = TickCount();
GetMouse(&where);
delayTime -= 3;
if (delayTime < 0) delayTime = 0;
scrollValue = 0;
goto tryAgain;
}
}
}
if (restorePict) DrawPicture(restorePict, &mustRect);
}
PicHandle GetArrow(DocumentPtr d, Boolean right, Rect *bounds)
{
PicHandle aPict;
Rect r;
if (d->noButtons) {
SetRect(bounds, 0, 0, 0, 0);
return GetPicture(1024);
}
if (!right) {
// left arrow
aPict = GetPicture(1024);
r = (**aPict).picFrame;
OffsetRect(&r, -r.left + 5, -r.top);
OffsetRect(&r, 0, d->w->portRect.bottom - r.bottom);
}
else {
// right arrow
aPict = GetPicture(1025);
r = (**aPict).picFrame;
OffsetRect(&r, -r.left, -r.top);
OffsetRect(&r, d->w->portRect.right - r.right - 5, d->w->portRect.bottom - r.bottom);
}
OffsetRect(&r, 0, -(d->thumbnailSize.bottom/2) + (r.bottom - r.top)/2);
OffsetRect(&r, 0, -(gSprockets->portRect.bottom * 3)/2);
if (bounds) *bounds = r;
return aPict;
}
void GetScrollArea(DocumentPtr d, Rect *bounds)
{
Rect r, r1, r2;
short bottom;
long maxWidth = (d->pageCount * d->thumbnailSize.right);
GetArrow(d, false, &r1);
GetArrow(d, true, &r2);
bottom = d->w->portRect.bottom - ((gSprockets->portRect.bottom * 3)/2);
SetRect(&r, r1.right, bottom - d->thumbnailSize.bottom, r2.left, bottom);
InsetRect(&r, 4, 0);
if ((r.right - r.left) > maxWidth) {
// don't wrap
short center = (r1.right + r2.left) / 2;
r.right = r.left + maxWidth;
OffsetRect(&r, -r.left + (center - (r.right - r.left)/2), 0);
d->noButtons = true;
}
*bounds = r;
}
void UpdateDocument(DocumentPtr d)
{
PicHandle aPict;
Rect r;
RgnHandle rgn = 0;
Rect scrollArea;
if (!d) return;
if (d->mc)
rgn = MCGetWindowRgn(d->mc, d->w);
scrollArea = d->scrollArea;
BeginUpdate(d->w);
SetPort(d->w);
ClipRect(&d->w->portRect);
if (rgn) {
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
RectRgn(rgn, &d->scrollAndSprocketsArea);
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
RectRgn(rgn, &d->titleRect);
DiffRgn(d->w->clipRgn, rgn, d->w->clipRgn);
}
RGBForeColor(&d->backgroundColor);
PaintRect(&d->w->portRect);
ForeColor(blackColor);
if (rgn)
UnionRgn(d->w->clipRgn, rgn, d->w->clipRgn);
// draw the title
LoadResource((Handle)d->titleBackground);
HNoPurge((Handle)d->titleBackground);
DrawPicture(d->titleBackground, &d->titleRect);
HPurge((Handle)d->titleBackground);
MoveTo(d->titlePlace.h, d->titlePlace.v);
TextFont(GetSysFont());
DrawString(d->movieName);
// left arrow
aPict = GetArrow(d, false, &r);
DrawPicture(aPict, &r);
// right arrow
aPict = GetArrow(d, true, &r);
DrawPicture(aPict, &r);
// sprockets
{
Rect r1 = d->sprocketsRectTop;
Rect r2 = d->sprocketsRectBottom;
Rect clip;
short pageOffset;
UnionRect(&r1, &r2, &clip);
ClipRect(&clip);
pageOffset = d->scrollPhaseShift;
r1.left -= pageOffset;
r2.left = r1.left;
r1.right = r1.left + gSprockets->portRect.right;
r2.right = r1.right;
while (r1.left < d->scrollArea.right) {
CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect,
&r1, srcCopy, nil);
CopyBits((BitMap *)*gSprockets->portPixMap, &d->w->portBits, &gSprockets->portRect,
&r2, srcCopy, nil);
OffsetRect(&r1, gSprockets->portRect.right, 0);
OffsetRect(&r2, gSprockets->portRect.right, 0);
}
}
// thumbnails
{
short firstPage;
short resID;
Rect thumbRect;
short saveRes = CurResFile();
r = scrollArea;
ClipRect(&r);
firstPage = d->scrollOffset;
resID = firstPage + 128;
thumbRect = r;
thumbRect.right = thumbRect.left + d->thumbnailSize.right;
OffsetRect(&thumbRect, -d->scrollPhaseShift, 0);
UseResFile(d->resRef);
while (thumbRect.left < r.right) {
Rect whoCares;
if ((resID - 128) >= d->pageCount)
resID = 128;
if (SectRect(&(**d->w->visRgn).rgnBBox, &thumbRect, &whoCares)) {
PicHandle p = GetPicture(resID);
MoveTo(thumbRect.left, thumbRect.top);
LineTo(thumbRect.left, thumbRect.bottom);
MoveTo(thumbRect.right - 1, thumbRect.top);
LineTo(thumbRect.right - 1, thumbRect.bottom);
if (p) {
Rect r = thumbRect;
r.right--;
r.left++;
LoadResource((Handle)p);
HNoPurge((Handle)p);
DrawPicture(p, &r);
HPurge((Handle)p);
}
}
OffsetRect(&thumbRect, d->thumbnailSize.right, 0);
resID++;
}
UseResFile(saveRes);
}
ClipRect(&d->w->portRect);
// dividing line
{
Rect r = d->scrollAndSprocketsArea;
RGBColor aColor;
r.left = 0;
r.right = d->w->portRect.right;
r.top -= (gSprockets->portRect.bottom/2) + 2;
aColor = d->backgroundColor;
aColor.red -= (aColor.red /6);
aColor.green -= (aColor.green /6);
aColor.blue -= (aColor.blue /6);
RGBForeColor(&aColor);
MoveTo(r.left, r.top);
LineTo(r.right, r.top);
aColor = d->backgroundColor;
aColor.red += (aColor.red /6);
aColor.green += (aColor.green /6);
aColor.blue += (aColor.blue /6);
RGBForeColor(&aColor);
MoveTo(r.left, r.top + 1);
LineTo(r.right, r.top + 1);
}
EndUpdate(d->w);
if (rgn) DisposeRgn(rgn);
}
void ActivateDocument(DocumentPtr d)
{
MenuHandle mh = GetMHandle(130);
short count, index = 0;
Ptr p;
char c[2];
count = CountMItems(mh);
while (count--)
DelMenuItem(mh, count + 1);
if (!d) return;
count = d->pageCount;
HLock(d->names);
p = *d->names;
c[0] = 1;
c[1] = 'e';
while (count--) {
AppendMenu(mh, (StringPtr)&c);
SetItem(mh, ++index, (StringPtr)p);
p += (*p + 1);
}
HUnlock(d->names);
}
long IdleOneDocument(DocumentPtr d, void *refCon)
{
if (d->mc)
MCIdle(d->mc);
return 0;
}
long ForEachDocument(DocFunction df, void *refCon)
{
WindowPtr w = FrontWindow();
long result = 0;
while (w) {
DocumentPtr d = GetWindowDocument(w);
if (d) {
result = (df)(d, refCon);
if (result) break;
}
w = (WindowPtr)((WindowPeek)w)->nextWindow;
}
return result;
}
long TestOneEvent(DocumentPtr d, EventRecord *e)
{
if (d->mc && d->m)
return MCIsPlayerEvent(d->mc, e);
return 0;
}
void OpenFinderDocs(void)
{
short printIt, docCount; // no printing
CountAppFiles(&printIt, &docCount);
if (docCount > 0) {
short j;
for(j = 1; j <= docCount; j++){
FSSpec fss;
AppFile apfile;
GetAppFiles(j,&apfile);
FSMakeFSSpec(apfile.vRefNum, 0, apfile.fName, &fss);
OpenDocument(&fss);
ClrAppFiles(j);
}
}
}
OSErr MissedAEParameters (AppleEvent *message)
{
DescType typeCode;
Size actualSize;
OSErr err;
err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
&typeCode, nil, 0L, &actualSize);
if (err == errAEDescNotFound)
return(noErr);
return(err = noErr ? errAEEventNotHandled : err);
}
pascal OSErr OpenDocMessage(AppleEvent *message, AppleEvent *reply, long refcon)
{
FSSpec fss;
AEDescList docList;
long index, itemsInList;
Size actualSize;
AEKeyword keywd;
DescType typeCode;
OSErr err;
if ((err = AEGetParamDesc(message, keyDirectObject, typeAEList, &docList)) != noErr)
return(err);
if ((err = MissedAEParameters(message)) != noErr)
return(err);
if ((err = AECountItems(&docList, &itemsInList)) != noErr)
return(err);
for (index = 1; index <= itemsInList; index++)
{
if ((err = AEGetNthPtr(&docList, index, typeFSS, &keywd, &typeCode,
(Ptr)&fss, sizeof(FSSpec), &actualSize)) != noErr)
break;
OpenDocument(&fss);
}
return(AEDisposeDesc(&docList));
}
pascal OSErr QuitAppMessage(AppleEvent *message, AppleEvent *reply, long refcon)
{
OSErr err;
if ((err = MissedAEParameters(message)) != noErr)
return(err);
gDone = true;
return(noErr);
}
void main(void)
{
OSErr err;
long response;
// initialize the world
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
InitCursor();
MaxApplZone();
// find the system version (used later)
Gestalt(gestaltSystemVersion, &gSysVersion);
gSysVersion = (gSysVersion >> 8) & 0x0F;
// must have QuickTime around
if (Gestalt(gestaltQuickTime, &response)) {
doAnAlert("\pPlease install QuickTime™.", 0);
return;
}
if (response < 0x01508000) {
doAnAlert("\pMovieBrowser™ required QuickTime 1.5 or later.", 0);
return;
}
err = EnterMovies();
if (err) {
doAnAlert("\pEnterMovies failed.", err);
return;
}
SetMenuBar(GetNewMBar(128));
DrawMenuBar();
AddResMenu(GetMHandle(128), 'DRVR');
gAppResFile = CurResFile();
gLastSearchText[0] = 0;
gLastWNETime = TickCount();
// load up the sprockets picture
{
PicHandle p = GetPicture(1028);
Rect r;
CGrafPtr savePort;
GDHandle saveGD;
if (!p) return;
r = (**p).picFrame;
if (NewGWorld(&gSprockets, 1, &r, 0, 0, 0) != noErr) {
doAnAlert("\pOut of memory", -108);
return;
}
LockPixels(gSprockets->portPixMap);
GetGWorld(&savePort, &saveGD);
SetGWorld(gSprockets, nil);
EraseRect(&r);
DrawPicture(p, &r);
SetGWorld(savePort, saveGD);
ReleaseResource((Handle)p);
}
if((Gestalt(gestaltAppleEventsAttr, &response) ? false : response != 0)) {
AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
(AEEventHandlerProcPtr)OpenDocMessage, 0, false);
AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
(AEEventHandlerProcPtr)QuitAppMessage, 0, false);
}
OpenFinderDocs();
do {
EventRecord e;
long result;
DocumentPtr d;
unsigned long ticksNow = TickCount();
Boolean mustGetEvent = gInBackground;
if (!mustGetEvent) {
// see if we have a pending update
WindowRef w = LMGetWindowList();
while (w) {
if (!EmptyRect(&(**((WindowPeek)w)->updateRgn).rgnBBox)) {
mustGetEvent = true;
break;
}
w = (WindowPtr)(((WindowPeek)w)->nextWindow);
}
}
if (mustGetEvent || ((gLastWNETime + kWNEInterval) < ticksNow)) {
WaitNextEvent(everyEvent, &e, 0, nil);
gLastWNETime = ticksNow;
}
else {
if (OSEventAvail(mDownMask | keyDownMask, &e))
WaitNextEvent(everyEvent, &e, 0, nil);
else
e.what = nullEvent;
}
#ifdef THINK_C
result = ForEachDocument((DocFunction)TestOneEvent, &e);
#else
result = ForEachDocument(TestOneEvent, &e);
#endif
if (result) continue;
switch (e.what) {
case mouseDown:
{
short part;
WindowPtr whichWindow;
part = FindWindow(e.where, &whichWindow);
if (part) {
switch (part) {
case inMenuBar:
colorMenus();
gDone = doMenuItem(MenuSelect(e.where));
break;
case inSysWindow:
SystemClick(&e, whichWindow);
break;
case inContent:
if (whichWindow != FrontWindow()) {
SelectWindow(whichWindow);
break;
}
DoContentClick(GetWindowDocument(whichWindow), e.where, e.when);
break;
case inDrag:
d = GetWindowDocument(whichWindow);
if (d != NULL) {
Rect r;
GetMovieBox(d->m, &r);
DragAlignedWindow(whichWindow, e.where, &qd.screenBits.bounds, &r, nil);
}
else
DragWindow(whichWindow, e.where, &qd.screenBits.bounds);
break;
case inGrow:
break;
case inGoAway:
if (TrackGoAway(whichWindow, e.where))
CloseDocument(GetWindowDocument(whichWindow));
break;
}
}
}
break;
case updateEvt:
UpdateDocument(GetWindowDocument((WindowPtr)e.message));
break;
case keyDown:
{
char c;
c = e.message & charCodeMask;
if (e.modifiers & cmdKey) {
colorMenus();
gDone = doMenuItem(MenuKey(c));
}
}
break;
case app4Evt:
if ((e.message & 0xFF000000L) == 0x01000000L) {
if (e.message & 1) {
InitCursor();
ActivateDocument(GetWindowDocument(FrontWindow()));
gInBackground = false;
}
else
gInBackground = true;
}
break;
case activateEvt:
ActivateDocument(GetWindowDocument((WindowPtr)e.message));
break;
case kHighLevelEvent:
AEProcessAppleEvent(&e);
break;
}
} while (!gDone);
// QuickTime will take care of cleaning up after itself...
}