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.
Feature Files/VRMovies.c
////////// |
// |
// File: VRMovies.c |
// |
// Contains: Support for QuickTime movie playback in VR nodes. |
// |
// Written by: Tim Monroe |
// Some code borrowed from QTVRSamplePlayer by Bryce Wolfson. |
// |
// Copyright: © 1996-1998 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <31> 03/17/00 rtm made changes to get things running under CarbonLib |
// <30> 09/10/99 rtm added code to implement hide regions |
// <29> 06/30/99 rtm added fix to VRMoov_LoadEmbeddedMovie to call VRMoov_SetOneBalanceAndVolume |
// only for localized sounds |
// <28> 06/29/99 rtm reworked VRMoov_LoopEmbeddedMovie to support palindrome looping |
// <27> 06/24/99 rtm major overhaul of geometry handling, using newly-revised code from |
// VRMovies project; removed USE_COPYBITS_TO_BACKBUFFER flag, since we now |
// always use DecompressSequenceFrameS |
// <26> 05/17/99 rtm reworked geometry handling to support horizontal back buffer in QT 4.0, |
// using code from revised VRMovies project; this code now automatically |
// determines whether the back buffer is oriented horizontally or not and |
// then does the right thing in either case |
// <25> 04/07/99 rtm revised VRMoov_StartMovie |
// <24> 03/29/99 rtm added VRMoov_Init and VRMoov_Stop; conditionalized out the support for |
// on-the-fly movie rotation (too many problems reported) |
// <23> 03/29/99 rtm added VRMoov_StartMovie as a wrapper for StartMovie to handle streamed |
// movies; changed StartMovie to VRMoov_StartMovie passim |
// <22> 01/26/99 rtm changed two occurrences of gw->portPixMap to GetGWorldPixMap(gw) |
// <21> 12/03/98 rtm modified VRMoov_LoadEmbeddedMovie to accept a string as a parameter, |
// which can now be a full URL or a pathname |
// <20> 09/28/98 rtm added call to DisposeMovie in VRMoov_PlayTransitionMovie to plug leak |
// <19> 09/11/98 rtm added code to use DecompressImage instead of CopyBits when copying |
// an embedded movie frame into the backbuffer; set the compiler flag |
// USE_COPYBITS_TO_BACKBUFFER in VRMovies.h to select the desired call |
// <18> 05/04/98 rtm added support for on-the-fly movie rotation |
// <17> 05/01/98 rtm added VRMoov_DoIdle call to VRMoov_PlayTransitionMovie, to service |
// scene-wide sounds while a transition movie is playing; also added |
// call to FlushEvents and cleaned up surrounding code |
// <16> 10/29/97 rtm modified VRMoov_SetVideoGraphicsMode to use GetMovieIndTrackType |
// <15> 09/18/97 rtm added parameter to VRMoov_CheckForCompletedMovies |
// <14> 06/24/97 rtm modified VRMoov_DoIdle to service QuickTime movies with video tracks |
// in non-frontmost windows |
// <13> 06/19/97 rtm added support for scene-wide sound-only movies |
// <12> 05/13/97 rtm added VRMoov_PlayTransitionMovie |
// <11> 04/28/97 rtm reworked to support sound-only movie files as well |
// <10> 04/28/97 rtm added VRMoov_PlayMovie; reworked passim to use linked list |
// <9> 03/17/97 rtm added VRMoov_SetMovieBalanceAndVolume |
// <8> 03/12/97 rtm copied file from VRMovies project and integrated with VRScript |
// <7> 03/06/97 rtm started to implement video masking |
// <6> 03/05/97 rtm added VRMoov_SetChromaColor; added fChromaColor to app data record |
// <5> 03/04/97 rtm fixed compositing problems at back buffer edges |
// <4> 03/03/97 rtm added VRMoov_SetVideoGraphicsMode to handle compositing |
// without using an offscreen GWorld |
// <3> 02/27/97 rtm further development: borrowed some ideas from QTVRSamplePlayer; |
// added VRMoov_SetEmbeddedMovieWidth etc. |
// <2> 12/12/96 rtm further development: borrowed some ideas from BoxMoov demo |
// <1> 12/11/96 rtm first file |
// |
// This code supports playing QuickTime movies in QTVR panoramas. For movies with video tracks, |
// this code draws the QuickTime movie frames into the back buffer, either directly or indirectly |
// (via an offscreen GWorld). Direct drawing gives the best performance, but indirect drawing is |
// necessary for some visual effects. |
// |
////////// |
// TO DO: |
// + finish video masking by custom 'hide' hot spots (so video goes *behind* such hot spots) |
// + verify that everything works okay if *images* are used instead of movies (scaling seems to be a problem) |
////////// |
// |
// header files |
// |
////////// |
#include "VRMovies.h" |
#include "VRScript.h" |
////////// |
// |
// constants |
// |
////////// |
const RGBColor kBlackColor = {0x0000, 0x0000, 0x0000}; // black |
const RGBColor kWhiteColor = {0xffff, 0xffff, 0xffff}; // white |
////////// |
// |
// global variables |
// |
////////// |
MoviePrePrerollCompleteUPP gMoviePPRollCompleteProc = NULL; // a routine descriptor for our pre-preroll completion routine |
////////// |
// |
// VRMoov_Init |
// Initialize for QuickTime movie playback. |
// |
////////// |
void VRMoov_Init (void) |
{ |
// allocate a routine descriptor for our pre-preroll completion routine |
if (gMoviePPRollCompleteProc == NULL) |
gMoviePPRollCompleteProc = NewMoviePrePrerollCompleteUPP(VRScript_MoviePrePrerollCompleteProc); |
} |
////////// |
// |
// VRMoov_Stop |
// Close down for QuickTime movie playback. |
// |
////////// |
void VRMoov_Stop (void) |
{ |
// deallocate routine descriptor |
if (gMoviePPRollCompleteProc != NULL) |
DisposeMoviePrePrerollCompleteUPP(gMoviePPRollCompleteProc); |
} |
////////// |
// |
// VRMoov_StartMovie |
// Start a QuickTime movie playing. |
// |
// This is essentially just a wrapper for StartMovie, to handle preprerolling of streamed movies. |
// |
////////// |
void VRMoov_StartMovie (Movie theMovie) |
{ |
PrePrerollMovie(theMovie, 0, GetMoviePreferredRate(theMovie), gMoviePPRollCompleteProc, (void *)0L); |
} |
////////// |
// |
// VRMoov_PlayMovie |
// Start a QuickTime movie playing or stop one from playing. |
// |
////////// |
void VRMoov_PlayMovie ( |
WindowObject theWindowObject, |
UInt32 theNodeID, |
UInt32 theEntryID, |
float thePanAngle, |
float theTiltAngle, |
float theScale, |
float theWidth, |
UInt32 theKeyRed, |
UInt32 theKeyGreen, |
UInt32 theKeyBlue, |
Boolean theUseBuffer, |
Boolean theUseCenter, |
Boolean theUseKey, |
Boolean theUseHide, |
Boolean theUseDir, |
Boolean theRotate, |
float theVolAngle, |
UInt32 theMode, |
UInt32 theOptions, |
char *thePathName) |
{ |
ApplicationDataHdl myAppData; |
Boolean myNeedPlayMovie = false; |
Boolean myNeedLoadMovie = false; |
VRScriptMoviePtr myPointer = NULL; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// see if this movie is already in our list of playing movies |
myPointer = (VRScriptMoviePtr)VRScript_GetObjectByEntryID(theWindowObject, kVREntry_QTMovie, theEntryID); |
if (myPointer == NULL) { |
// this movie isn't in our list yet, so we'll need to add it to the list |
myNeedLoadMovie = true; |
myNeedPlayMovie = true; |
} else { |
// this movie is already in our list; theOptions determines how we handle this request: |
switch (theOptions) { |
case kVRMedia_PlayNew: |
// start the movie playing (whether it's already playing or not); |
// multiple movies aren't supported in QTVR 2.0, so we just map to kVRMedia_Continue |
myNeedPlayMovie = true; |
myNeedLoadMovie = true; |
break; |
case kVRMedia_Restart: |
// stop the current movie and then restart it; use the existing movie data |
StopMovie(myPointer->fMovie); |
myNeedPlayMovie = true; |
myNeedLoadMovie = false; |
break; |
case kVRMedia_ToggleStop: |
// toggle the movie's current play/stop state |
myNeedLoadMovie = false; |
if (!IsMovieDone(myPointer->fMovie)) { |
// stop the movie and get rid of movie list entry |
StopMovie(myPointer->fMovie); |
VRScript_DelistEntry(theWindowObject, (VRScriptGenericPtr)myPointer); |
myNeedPlayMovie = false; |
} else { |
// start the movie; use the existing movie data |
myNeedPlayMovie = true; |
} |
break; |
case kVRMedia_TogglePause: |
// toggle the movie's current play/pause state |
myNeedLoadMovie = false; |
if (GetMovieRate(myPointer->fMovie) != (Fixed)0) { |
// stop the movie |
StopMovie(myPointer->fMovie); |
myNeedPlayMovie = false; |
} else { |
// restart the movie; use the existing movie data |
myNeedPlayMovie = false; |
StartMovie(myPointer->fMovie); |
} |
break; |
case kVRMedia_Continue: |
// just let the movie already in progress continue |
myNeedPlayMovie = false; |
myNeedLoadMovie = false; |
break; |
case kVRMedia_Stop: |
// stop the current movie |
StopMovie(myPointer->fMovie); |
myNeedPlayMovie = false; |
myNeedLoadMovie = false; |
break; |
default: |
// unrecognized option; start the movie playing |
myNeedPlayMovie = true; |
myNeedLoadMovie = false; |
break; |
} |
} |
if (myNeedLoadMovie) { |
myPointer = VRScript_EnlistMovie ( |
theWindowObject, |
theNodeID, |
theEntryID, |
thePanAngle, |
theTiltAngle, |
theScale, |
theWidth, |
theKeyRed, |
theKeyGreen, |
theKeyBlue, |
theUseBuffer, |
theUseCenter, |
theUseKey, |
theUseHide, |
theUseDir, |
theRotate, |
theVolAngle, |
theMode, |
theOptions, |
thePathName); |
} |
if (myNeedPlayMovie) |
if (myPointer != NULL) |
VRMoov_LoadEmbeddedMovie(thePathName, theWindowObject, myPointer); |
} |
////////// |
// |
// VRMoov_PlayTransitionMovie |
// Play a QuickTime movie as a transition from one node to another. |
// |
////////// |
void VRMoov_PlayTransitionMovie (WindowObject theWindowObject, UInt32 theOptions, char *thePathName) |
{ |
FSSpec myFSSpec; |
short myMovieFileRef = 0; |
Movie myMovie; |
Rect myRect; |
GWorldPtr myGWorld; |
GDHandle myGDevice; |
long myCount = 0; |
Boolean myUserCancelled = false; |
OSErr myErr = noErr; |
if ((theWindowObject == NULL) || (thePathName == NULL)) |
goto bail; |
FileUtils_MakeFSSpecForPathName(0, 0L, thePathName, &myFSSpec); |
// open the movie |
myErr = OpenMovieFile(&myFSSpec, &myMovieFileRef, fsRdPerm); |
if (myErr != noErr) |
goto bail; |
myErr = NewMovieFromFile(&myMovie, myMovieFileRef, NULL, NULL, newMovieActive, NULL); |
if ((myErr != noErr) || (myMovie == NULL)) |
goto bail; |
// set the movie GWorld |
GetMovieGWorld((**theWindowObject).fMovie, &myGWorld, &myGDevice); |
SetMovieGWorld(myMovie, myGWorld, myGDevice); |
// set the movie box to the size of the QTVR window |
GetMovieBox((**theWindowObject).fMovie, &myRect); |
SetMovieBox(myMovie, &myRect); |
// start the movie |
GoToBeginningOfMovie(myMovie); |
VRMoov_StartMovie(myMovie); |
// play the movie once thru |
while (!IsMovieDone(myMovie) && !myUserCancelled) { |
MoviesTask(myMovie, 0); |
#if !TARGET_API_MAC_CARBON |
SystemTask(); |
#endif |
// on very long transition movies (or very slow machines), scene-wide sound-only movies need to be serviced |
// (but not every time thru the loop, eh?) |
if (myCount % kDoIdleStep == 0) |
VRMoov_DoIdle(theWindowObject); |
myCount++; |
// see if the user has cancelled the transition movie, if so allowed |
if (theOptions == kVRMovie_PlayTilClick) |
myUserCancelled = Button(); |
} |
StopMovie(myMovie); |
DisposeMovie(myMovie); |
// button clicks during a transition movie remain in the OS event queue (even if detected by the |
// Button call above); we'd better remove them (by calling FlushEvents) or they may trigger a hot |
// spot in the destination node; note that if theOptions is kVRMovie_PlayTilClick, then the first |
// click stops the movie and gets flushed, but any subsequent clicks remain in the OS event queue |
// and get processed normally.... |
FlushEvents(mDownMask + mUpMask, 0); |
bail: |
if (myMovieFileRef != 0) |
CloseMovieFile(myMovieFileRef); |
} |
////////// |
// |
// VRMoov_LoadEmbeddedMovie |
// Load the QuickTime movie in the specified file. |
// Returns a Boolean to indicate success (true) or failure (false). |
// |
////////// |
Boolean VRMoov_LoadEmbeddedMovie (char *thePathName, WindowObject theWindowObject, VRScriptMoviePtr theEntry) |
{ |
FSSpec myFSSpec; |
short myMovieFileRef = 0; |
Movie myMovie = NULL; |
GWorldPtr myGWorld = NULL; |
Rect myRect; |
ApplicationDataHdl myAppData = NULL; |
QTVRInstance myInstance = NULL; |
OSErr myErr = paramErr; |
////////// |
// |
// validate the window object and application data |
// |
////////// |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
goto bail; |
if (theEntry == NULL) |
goto bail; |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
goto bail; |
HLock((Handle)myAppData); |
////////// |
// |
// open the movie file and the movie |
// |
////////// |
if (URLUtils_IsAbsoluteURL(thePathName)) { |
// we were passed a URL |
myMovie = URLUtils_NewMovieFromURL(thePathName, newMovieActive, NULL); |
if (myMovie == NULL) |
goto bail; |
} else { |
// we were passed a filename; create an FSSpec for the file |
FileUtils_MakeFSSpecForPathName(0, 0L, thePathName, &myFSSpec); |
// open the movie |
myErr = OpenMovieFile(&myFSSpec, &myMovieFileRef, fsRdPerm); |
if (myErr != noErr) |
goto bail; |
myErr = NewMovieFromFile(&myMovie, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL); |
if (myErr != noErr) |
goto bail; |
} |
////////// |
// |
// get the movie geometry |
// |
////////// |
GetMovieBox(myMovie, &myRect); |
GetMovieMatrix(myMovie, &theEntry->fOrigMovieMatrix); |
MacOffsetRect(&myRect, -myRect.left, -myRect.top); |
SetMovieBox(myMovie, &myRect); |
// determine the orientation of the back buffer |
(**myAppData).fBackBufferIsHoriz = QTVRUtils_IsBackBufferHorizontal((**theWindowObject).fInstance); |
// keep track of the movie and movie rectangle |
theEntry->fMovie = myMovie; |
theEntry->fMovieBox = myRect; |
////////// |
// |
// determine what kinds of media are in this movie |
// |
////////// |
// we cannot query a streamed movie for its media types until it's been preprerolled, which we don't want to do now; |
// as a result, we'll do the best we can |
if (QTUtils_IsStreamedMovie(myMovie)) { |
theEntry->fQTMovieHasSound = true; |
theEntry->fQTMovieHasVideo = !EmptyRect(&myRect); |
} else { |
theEntry->fQTMovieHasSound = QTUtils_IsMediaTypeInMovie(myMovie, SoundMediaType) || QTUtils_IsMediaTypeInMovie(myMovie, MusicMediaType); |
theEntry->fQTMovieHasVideo = QTUtils_IsMediaTypeInMovie(myMovie, VideoMediaType); |
} |
////////// |
// |
// do processing for video media |
// |
////////// |
if (theEntry->fQTMovieHasVideo) { |
// get rid of any existing offscreen graphics world |
if (theEntry->fOffscreenGWorld != NULL) { |
UnlockPixels(theEntry->fOffscreenPixMap); |
DisposeGWorld(theEntry->fOffscreenGWorld); |
theEntry->fOffscreenGWorld = NULL; |
} |
// clear out any existing custom cover function and reset the video media graphics mode |
// (these may have been modified for direct-screen drawing) |
SetMovieCoverProcs(myMovie, NULL, NULL, 0); |
VRMoov_SetVideoGraphicsMode(myMovie, theEntry, false); |
// if necessary, create an offscreen graphics world; |
// this is where we'll image the movie before copying it into the back buffer |
// when we want to do special effects |
if (theEntry->fUseOffscreenGWorld) { |
myErr = NewGWorld(&myGWorld, 0, &myRect, NULL, NULL, 0); |
theEntry->fOffscreenGWorld = myGWorld; |
theEntry->fOffscreenPixMap = GetGWorldPixMap(myGWorld); |
// make an image description, which is needed by DecompressSequenceBegin |
LockPixels(theEntry->fOffscreenPixMap); |
MakeImageDescriptionForPixMap(theEntry->fOffscreenPixMap, &(theEntry->fImageDesc)); |
UnlockPixels(theEntry->fOffscreenPixMap); |
} else { |
// set the video media graphics mode to drop out the chroma key color in a movie; |
// we also need to install an uncover function that doesn't erase the uncovered region |
if (theEntry->fCompositeMovie) { |
VRMoov_SetVideoGraphicsMode(myMovie, theEntry, true); |
SetMovieCoverProcs(myMovie, NewMovieRgnCoverUPP(VRMoov_CoverProc), NULL, (long)theWindowObject); |
} |
} |
// turn on view-changed flag, so hide region gets calculated (if necessary) |
(**myAppData).fViewHasChanged = true; |
} |
////////// |
// |
// do processing for sound media |
// |
////////// |
if (theEntry->fQTMovieHasSound) { |
// get the sound media handler |
theEntry->fMediaHandler = QTUtils_GetSoundMediaHandler(myMovie); |
// set initial balance and volume for localized sounds |
if (theEntry->fSoundIsLocalized) { |
VRMoov_SetOneBalanceAndVolume(myMovie, theEntry->fMediaHandler, QTVRGetPanAngle(myInstance), QTVRGetTiltAngle(myInstance), theEntry->fMovieCenter.x, theEntry->fVolAngle); |
(**myAppData).fSoundHasChanged = true; |
} |
} |
////////// |
// |
// install the back-buffer imaging procedure |
// |
////////// |
if ((**theWindowObject).fInstance != NULL) |
VRScript_InstallBackBufferImagingProc((**theWindowObject).fInstance, theWindowObject); |
////////// |
// |
// start the movie playing |
// |
////////// |
switch (theEntry->fMode) { |
case kVRPlay_Once: // play the movie once thru |
GoToBeginningOfMovie(myMovie); |
VRMoov_StartMovie(myMovie); |
break; |
case kVRPlay_Loop: // start the movie playing in a loop |
VRMoov_LoopEmbeddedMovie(myMovie, false); |
break; |
case kVRPlay_LoopPalindrome: // start the movie playing in a palindrome loop |
VRMoov_LoopEmbeddedMovie(myMovie, true); |
break; |
} |
bail: |
// we don't want to edit the embedded movie, so we can close the movie file |
if (myMovieFileRef != 0) |
CloseMovieFile(myMovieFileRef); |
HUnlock((Handle)myAppData); |
return(myErr == noErr); |
} |
////////// |
// |
// VRMoov_LoopEmbeddedMovie |
// Start the QuickTime movie playing in a loop. |
// |
////////// |
void VRMoov_LoopEmbeddedMovie (Movie theMovie, Boolean isPalindrome) |
{ |
TimeBase myTimeBase; |
long myFlags = 0L; |
// set the movie's play hints to enhance looping performance |
SetMoviePlayHints(theMovie, hintsLoop, hintsLoop); |
// set the looping flag of the movie's time base |
myTimeBase = GetMovieTimeBase(theMovie); |
myFlags = GetTimeBaseFlags(myTimeBase); |
myFlags |= loopTimeBase; |
// set or clear the palindrome flag, depending on the specified setting |
if (isPalindrome) |
myFlags |= palindromeLoopTimeBase; |
else |
myFlags &= ~palindromeLoopTimeBase; |
SetTimeBaseFlags(myTimeBase, myFlags); |
// start playing the movie |
VRMoov_StartMovie(theMovie); |
} |
////////// |
// |
// VRMoov_DoIdle |
// Do any movie-related processing that can or should occur at idle time. |
// Returns true if the caller should call QTVRUpdate, false otherwise. |
// |
////////// |
Boolean VRMoov_DoIdle (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
VRScriptMoviePtr myPointer; |
Boolean myNeedUpdate = false; |
if ((**theWindowObject).fInstance == NULL) |
return(myNeedUpdate); |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(myNeedUpdate); |
// walk the linked list and service any embedded sound-only movies |
myPointer = (VRScriptMoviePtr)(**myAppData).fListArray[kVREntry_QTMovie]; |
while (myPointer != NULL) { |
if (myPointer->fQTMovieHasSound && !(myPointer->fQTMovieHasVideo)) { |
MoviesTask(myPointer->fMovie, 0L); |
} |
myPointer = myPointer->fNextEntry; |
} |
// now service the (single) embedded video movie, if there is one |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) { |
// trip the back buffer procedure, which internally calls MoviesTask; |
// note that this is necessary *only* if the window containing the embedded movie |
// isn't the frontmost window |
if ((**theWindowObject).fWindow != QTFrame_GetFrontAppWindow()) |
myNeedUpdate = true; |
} |
return(myNeedUpdate); |
} |
////////// |
// |
// VRMoov_DumpNodeMovies |
// Stop playing all movies enlisted for the current node. |
// |
////////// |
void VRMoov_DumpNodeMovies (WindowObject theWindowObject) |
{ |
VRMoov_DumpSelectedMovies(theWindowObject, kVRSelect_Node); |
} |
////////// |
// |
// VRMoov_DumpSceneMovies |
// Stop playing all movies enlisted for the current scene. |
// |
////////// |
void VRMoov_DumpSceneMovies (WindowObject theWindowObject) |
{ |
VRMoov_DumpSelectedMovies(theWindowObject, kVRSelect_Scene); |
} |
////////// |
// |
// VRMoov_DumpSelectedMovies |
// Stop any existing embedded movies from playing and then clean up. |
// |
////////// |
void VRMoov_DumpSelectedMovies (WindowObject theWindowObject, UInt32 theOptions) |
{ |
ApplicationDataHdl myAppData; |
VRScriptMoviePtr myPointer; |
VRScriptMoviePtr myNext; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// walk the movie list and dump any movies movies associated with this node |
myPointer = (VRScriptMoviePtr)(**myAppData).fListArray[kVREntry_QTMovie]; |
while (myPointer != NULL) { |
myNext = myPointer->fNextEntry; |
if (((myPointer->fNodeID != kVRAnyNode) && (theOptions == kVRSelect_Node)) || |
((myPointer->fNodeID == kVRAnyNode) && (theOptions == kVRSelect_Scene))) |
VRScript_DelistEntry(theWindowObject, (VRScriptGenericPtr)myPointer); |
myPointer = myNext; |
} |
// clear the existing back buffer imaging proc |
QTVRSetBackBufferImagingProc((**theWindowObject).fInstance, NULL, 0, NULL, 0); |
// make sure the back buffer is clean |
QTVRRefreshBackBuffer((**theWindowObject).fInstance, 0); |
return; |
} |
////////// |
// |
// VRMoov_GetEmbeddedVideo |
// Return the first embedded QuickTime movie that has a video track. |
// |
////////// |
VRScriptMoviePtr VRMoov_GetEmbeddedVideo (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
VRScriptMoviePtr myPointer = NULL; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(myPointer); |
// walk our linked list of movies to find the target movie |
myPointer = (VRScriptMoviePtr)(**myAppData).fListArray[kVREntry_QTMovie]; |
while (myPointer != NULL) { |
if (myPointer->fQTMovieHasVideo) |
return(myPointer); |
myPointer = myPointer->fNextEntry; |
} |
return(NULL); |
} |
////////// |
// |
// VRMoov_GetEmbeddedMovieWidth |
// Get the width of the embedded movie. |
// |
////////// |
float VRMoov_GetEmbeddedMovieWidth (WindowObject theWindowObject) |
{ |
float myWidth = 0.0; |
VRScriptMoviePtr myPointer; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) |
myWidth = myPointer->fMovieWidth; |
return(myWidth); |
} |
////////// |
// |
// VRMoov_SetEmbeddedMovieWidth |
// Set the width of the embedded movie. |
// |
////////// |
void VRMoov_SetEmbeddedMovieWidth (WindowObject theWindowObject, float theWidth) |
{ |
QTVRInstance myInstance; |
VRScriptMoviePtr myPointer; |
if (theWindowObject == NULL) |
return; |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
return; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) |
myPointer->fMovieWidth = theWidth; |
// clear out the existing area of interest |
QTVRRefreshBackBuffer(myInstance, 0); |
// reinstall the back buffer imaging procedure |
VRScript_InstallBackBufferImagingProc(myInstance, theWindowObject); |
} |
////////// |
// |
// VRMoov_GetEmbeddedMovieCenter |
// Get the center of the embedded movie. |
// |
////////// |
void VRMoov_GetEmbeddedMovieCenter (WindowObject theWindowObject, QTVRFloatPoint *theCenter) |
{ |
VRScriptMoviePtr myPointer; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer == NULL) { |
theCenter->x = 0.0; |
theCenter->y = 0.0; |
} else { |
theCenter->x = myPointer->fMovieCenter.x; |
theCenter->y = myPointer->fMovieCenter.y; |
} |
} |
////////// |
// |
// VRMoov_SetEmbeddedMovieCenter |
// Set the center of the embedded movie. |
// |
////////// |
void VRMoov_SetEmbeddedMovieCenter (WindowObject theWindowObject, const QTVRFloatPoint *theCenter) |
{ |
QTVRInstance myInstance; |
float myX, myY; |
VRScriptMoviePtr myPointer; |
if (theWindowObject == NULL) |
return; |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
return; |
myX = theCenter->x; |
myY = theCenter->y; |
// subject the values passed in to the current view constraints |
QTVRWrapAndConstrain(myInstance, kQTVRPan, myX, &myX); |
QTVRWrapAndConstrain(myInstance, kQTVRTilt, myY, &myY); |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) { |
myPointer->fMovieCenter.x = myX; |
myPointer->fMovieCenter.y = myY; |
} |
// clear out the existing area of interest |
QTVRRefreshBackBuffer(myInstance, 0); |
// reinstall the back buffer imaging procedure |
VRScript_InstallBackBufferImagingProc(myInstance, theWindowObject); |
} |
////////// |
// |
// VRMoov_GetEmbeddedMovieScale |
// Get the scale of the embedded movie. |
// |
////////// |
float VRMoov_GetEmbeddedMovieScale (WindowObject theWindowObject) |
{ |
float myScale; |
VRScriptMoviePtr myPointer; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer == NULL) |
myScale = 0.0; |
else |
myScale = myPointer->fMovieScale; |
return(myScale); |
} |
////////// |
// |
// VRMoov_SetEmbeddedMovieScale |
// Set the scale factor of the embedded movie. |
// |
////////// |
void VRMoov_SetEmbeddedMovieScale (WindowObject theWindowObject, float theScale) |
{ |
QTVRInstance myInstance; |
VRScriptMoviePtr myPointer; |
if (theWindowObject == NULL) |
return; |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
return; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) |
myPointer->fMovieScale = theScale; |
// clear out the existing area of interest |
QTVRRefreshBackBuffer(myInstance, 0); |
// reinstall the back buffer imaging procedure |
VRScript_InstallBackBufferImagingProc(myInstance, theWindowObject); |
} |
////////// |
// |
// VRMoov_GetEmbeddedMovieRect |
// Get the rectangle of the embedded movie. |
// |
////////// |
void VRMoov_GetEmbeddedMovieRect (WindowObject theWindowObject, Rect *theRect) |
{ |
VRScriptMoviePtr myPointer; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer == NULL) { |
theRect->left = 0.0; |
theRect->top = 0.0; |
theRect->right = 0.0; |
theRect->bottom = 0.0; |
} else { |
theRect->left = myPointer->fMovieBox.left; |
theRect->top = myPointer->fMovieBox.top; |
theRect->right = myPointer->fMovieBox.right; |
theRect->bottom = myPointer->fMovieBox.bottom; |
} |
} |
////////// |
// |
// VRMoov_SetEmbeddedMovieRect |
// Set the rectangle of the embedded movie. |
// |
////////// |
void VRMoov_SetEmbeddedMovieRect (WindowObject theWindowObject, const Rect *theRect) |
{ |
QTVRInstance myInstance; |
VRScriptMoviePtr myPointer; |
if (theWindowObject == NULL) |
return; |
myInstance = (**theWindowObject).fInstance; |
if (myInstance == NULL) |
return; |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer != NULL) { |
myPointer->fMovieBox.right = theRect->right; |
myPointer->fMovieBox.bottom = theRect->bottom; |
} |
// clear out the existing area of interest |
QTVRRefreshBackBuffer(myInstance, 0); |
// reinstall the back buffer imaging procedure |
VRScript_InstallBackBufferImagingProc(myInstance, theWindowObject); |
} |
////////// |
// |
// VRMoov_SetAllBalanceAndVolume |
// Set the balance and volume attenuation of all embedded QuickTime movies making sound. |
// |
////////// |
void VRMoov_SetAllBalanceAndVolume (WindowObject theWindowObject, float thePan, float theTilt) |
{ |
ApplicationDataHdl myAppData; |
VRScriptMoviePtr myPointer; |
#if QD3D_AVAIL |
VRScript3DObjPtr my3DObjPtr; |
#endif |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return; |
// walk our linked list of embedded QuickTime movies and set the balance and volume of any localized sounds |
myPointer = (VRScriptMoviePtr)(**myAppData).fListArray[kVREntry_QTMovie]; |
while (myPointer != NULL) { |
if (myPointer->fQTMovieHasSound) |
if (myPointer->fSoundIsLocalized) |
VRMoov_SetOneBalanceAndVolume(myPointer->fMovie, myPointer->fMediaHandler, thePan, theTilt, myPointer->fMovieCenter.x, myPointer->fVolAngle); |
myPointer = myPointer->fNextEntry; |
} |
#if QD3D_AVAIL |
// walk our linked list of 3D objects and set the balance and volume of any texture-mapped movies |
my3DObjPtr = (VRScript3DObjPtr)(**myAppData).fListArray[kVREntry_QD3DObject]; |
while (my3DObjPtr != NULL) { |
if (my3DObjPtr->fTexture != NULL) |
if (my3DObjPtr->fTextureIsMovie) |
if ((**my3DObjPtr->fTexture).fMediaHandler != NULL) |
VRMoov_SetOneBalanceAndVolume((**my3DObjPtr->fTexture).fMovie, (**my3DObjPtr->fTexture).fMediaHandler, thePan, theTilt, QTVRUtils_Point3DToPanAngle(-1.0 * my3DObjPtr->fGroupCenter.x, my3DObjPtr->fGroupCenter.y, -1.0 * my3DObjPtr->fGroupCenter.z), QTVRUtils_DegreesToRadians(kVR_TextureMovieVolAngle)); |
my3DObjPtr = my3DObjPtr->fNextEntry; |
} |
#endif |
} |
////////// |
// |
// VRMoov_SetOneBalanceAndVolume |
// Set the balance and volume attenuation of an embedded QuickTime movie. |
// |
////////// |
void VRMoov_SetOneBalanceAndVolume (Movie theMovie, MediaHandler theMediaHandler, float thePan, float theTilt, float theMoviePan, float theVolAngle) |
{ |
#pragma unused(theTilt) |
short myValue; |
float myPanDelta; |
float myCosDelta; // cosine of pan angle delta from movie center |
float myCosLimit; // cosine of attenuation cone limit angle |
myPanDelta = thePan - theMoviePan; |
// ***set the balance |
myValue = kQTMaxSoundVolume * sin(myPanDelta); |
MediaSetSoundBalance(theMediaHandler, myValue); |
// ***set the volume |
myCosDelta = cos(myPanDelta); |
myCosLimit = cos(theVolAngle); |
if (myCosDelta >= myCosLimit) |
// inside cone of attenuation, volume scales from 1.0 (at center) to 0.0 (at cone edge) |
myValue = kQTMaxSoundVolume * ((myCosDelta - myCosLimit) / (1 - myCosLimit)); |
else |
// outside cone of attenuation, volume is 0.0; |
myValue = kNoVolume; |
if (myValue != GetMovieVolume(theMovie)) |
SetMovieVolume(theMovie, myValue); |
} |
////////// |
// |
// VRMoov_CalcImagingMatrix |
// Calculate the movie matrix required to draw the embedded movie into the specified rectangle. |
// |
////////// |
OSErr VRMoov_CalcImagingMatrix (WindowObject theWindowObject, Rect *theBBufRect) |
{ |
ApplicationDataHdl myAppData = NULL; |
VRScriptMoviePtr myPointer = NULL; |
Rect myDestRect = *theBBufRect; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(paramErr); |
myPointer = VRMoov_GetEmbeddedVideo(theWindowObject); |
if (myPointer == NULL) |
return(paramErr); |
// reset the current movie matrix with the original movie matrix of the embedded movie; |
// we need to preserve that matrix in our calculations below if we are not drawing the |
// movie into an offscreen GWorld |
myPointer->fMovieMatrix = myPointer->fOrigMovieMatrix; |
// in general, it's easiest to construct the desired matrix by first doing the scaling |
// and then doing the rotation and translation (if necessary); so we need to swap the |
// right and bottom edges of the back buffer rectangle before doing the scaling, if a |
// rotation will also be necessary |
if (!(**myAppData).fBackBufferIsHoriz) { |
myDestRect.bottom = theBBufRect->right; |
myDestRect.right = theBBufRect->bottom; |
} |
// set up the scaling matrix |
// (MapMatrix concatenates the new matrix to the existing matrix, whereas RectMatrix first |
// sets the existing matrix to the identity matrix) |
if (myPointer->fUseOffscreenGWorld) |
RectMatrix(&myPointer->fMovieMatrix, &myPointer->fMovieBox, &myDestRect); |
else |
MapMatrix(&myPointer->fMovieMatrix, &myPointer->fMovieBox, &myDestRect); |
// add a rotation and translation, if necessary (and if requested to do so) |
if (!(**myAppData).fBackBufferIsHoriz) |
if (myPointer->fDoRotateMovie) { |
RotateMatrix(&myPointer->fMovieMatrix, Long2Fix(-90), 0, 0); |
TranslateMatrix(&myPointer->fMovieMatrix, 0, Long2Fix(RECT_HEIGHT(*theBBufRect))); |
} |
return(noErr); |
} |
////////// |
// |
// VRMoov_SetupDecompSeq |
// Set up the decompression sequence for DecompressSequenceFrameS. |
// |
// This needs to be called whenever either the rectangle or the GWorld of the back buffer changes. |
// |
////////// |
OSErr VRMoov_SetupDecompSeq (VRScriptMoviePtr theEntry, GWorldPtr theDestGWorld) |
{ |
short myMode = srcCopy; |
OSErr myErr = noErr; |
if (theEntry == NULL) |
return(paramErr); |
// make sure we don't have a decompression sequence already open |
VRMoov_RemoveDecompSeq(theEntry); |
// set up the transfer mode |
if (theEntry->fCompositeMovie) |
myMode = srcCopy | transparent; |
// set up the image decompression sequence |
myErr = DecompressSequenceBegin( &theEntry->fImageSequence, |
theEntry->fImageDesc, |
(CGrafPtr)theDestGWorld, |
NULL, |
NULL, // entire source image |
&theEntry->fMovieMatrix, |
myMode, |
NULL, // no mask |
0, |
(**(theEntry->fImageDesc)).spatialQuality, |
NULL); |
return(myErr); |
} |
////////// |
// |
// VRMoov_RemoveDecompSeq |
// Remove the decompression sequence for DecompressSequenceFrameS. |
// |
////////// |
OSErr VRMoov_RemoveDecompSeq (VRScriptMoviePtr theEntry) |
{ |
OSErr myErr = paramErr; |
if (theEntry != NULL) |
if (theEntry->fImageSequence != 0) { |
myErr = CDSequenceEnd(theEntry->fImageSequence); |
theEntry->fImageSequence = 0; |
} |
return(myErr); |
} |
////////// |
// |
// VRMoov_BackBufferImagingProc |
// The back buffer imaging procedure: |
// * get a frame of movie and image it into the back buffer |
// * also, do any additional compositing that might be desired |
// This function is called by VRScript_BackBufferImagingProc. |
// |
////////// |
PASCAL_RTN OSErr VRMoov_BackBufferImagingProc (QTVRInstance theInstance, Rect *theRect, UInt16 theAreaIndex, UInt32 theFlagsIn, UInt32 *theFlagsOut, SInt32 theRefCon) |
{ |
#pragma unused(theAreaIndex) |
WindowObject myWindowObject = (WindowObject)theRefCon; |
ApplicationDataHdl myAppData = NULL; |
Movie myMovie = NULL; |
Boolean myIsDrawing = theFlagsIn & kQTVRBackBufferRectVisible; |
VRScriptMoviePtr myPointer = NULL; |
GWorldPtr myBBufGWorld, myMovGWorld; |
GDHandle myBBufGDevice, myMovGDevice; |
Rect myRect; |
OSErr myErr = paramErr; |
////////// |
// |
// initialize; make sure that we've got the data we need to continue |
// |
////////// |
// assume we're not going to draw anything |
*theFlagsOut = 0; |
if ((theInstance == NULL) || (myWindowObject == NULL)) |
return(paramErr); |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject); |
if (myAppData == NULL) |
return(paramErr); |
myPointer = VRMoov_GetEmbeddedVideo(myWindowObject); |
if (myPointer == NULL) |
return(paramErr); |
HLock((Handle)myAppData); |
myMovie = myPointer->fMovie; |
if ((myMovie == NULL) || (IsMovieDone(myMovie))) { |
// we don't have an embedded movie or it's done playing, so remove this back-buffer imaging procedure |
QTVRSetBackBufferImagingProc((**myWindowObject).fInstance, NULL, 0, NULL, 0); |
goto bail; |
} |
////////// |
// |
// make sure that the movie GWorld is set correctly; |
// note that we call SetMovieGWorld only if we have to (for performance reasons) |
// |
////////// |
// get the current graphics world |
// (on entry, the current graphics world is [usually] set to the back buffer) |
GetGWorld(&myBBufGWorld, &myBBufGDevice); |
// get the embedded movie's graphics world |
GetMovieGWorld(myMovie, &myMovGWorld, &myMovGDevice); |
if (myPointer->fUseOffscreenGWorld) { |
// we're using an offscreen graphics world, so set movie's GWorld to be that offscreen graphics world |
if (myMovGWorld != myPointer->fOffscreenGWorld) |
SetMovieGWorld(myMovie, myPointer->fOffscreenGWorld, GetGWorldDevice(myPointer->fOffscreenGWorld)); |
} else { |
// we're not using an offscreen graphics world, so set movie GWorld to be the back buffer; |
if ((myMovGWorld != myBBufGWorld) || (myMovGDevice != myBBufGDevice)) |
SetMovieGWorld(myMovie, myBBufGWorld, myBBufGDevice); |
} |
////////// |
// |
// make sure the movie rectangle and movie matrix are set correctly |
// |
////////// |
if (myIsDrawing) { |
// if we weren't previously visible, make sure we are now |
GetMovieBox(myMovie, &myRect); |
if (EmptyRect(&myRect)) |
SetMovieBox(myMovie, &myPointer->fMovieBox); |
// when no offscreen GWorld is being used... |
if (!myPointer->fUseOffscreenGWorld) { |
// ...make sure the movie matrix is set correctly... |
if (!MacEqualRect(theRect, &myPointer->fPrevBBufRect)) { |
VRMoov_CalcImagingMatrix(myWindowObject, theRect); |
SetMovieMatrix(myMovie, &myPointer->fMovieMatrix); |
} |
// ...and, if we are compositing, force QuickTime to draw a movie frame when MoviesTask is called |
// (since the previous frame was automatically erased from the back buffer by QuickTime VR) |
if (myPointer->fCompositeMovie) |
UpdateMovie(myMovie); |
} |
} else { |
// if we're not visible, set the movie rectangle to an empty rectangle |
// so we're not wasting time trying to draw a movie frame |
MacSetRect(&myRect, 0, 0, 0, 0); |
SetMovieBox(myMovie, &myRect); |
} |
////////// |
// |
// draw a new movie frame into the movie's graphics world (and play movie sound) |
// |
////////// |
MoviesTask(myMovie, 0); |
// if we got here, everything is okay so far |
myErr = noErr; |
////////// |
// |
// perform any additional compositing |
// |
////////// |
// that is, draw, using the current chroma key color, anything to be dropped out of the image; |
// note that this technique works *only* if we're using an offscreen graphics world |
if (myPointer->fUseOffscreenGWorld && myPointer->fCompositeMovie && myPointer->fUseHideRegion && myIsDrawing) { |
RGBColor myColor; |
// recalculate the hide region, but only if the view has changed |
if ((**myAppData).fViewHasChanged) { |
Handle myHotSpotList = NewHandleClear(4); |
UInt32 myHotSpotCount = 0; |
UInt32 myHotSpotID = 0; |
OSType myHotSpotType; |
RgnHandle myHotSpotRgn = NULL; |
// dispose of any existing hide region |
if (myPointer->fHideRegion != NULL) |
DisposeRgn(myPointer->fHideRegion); |
// create a new, empty hide region |
myPointer->fHideRegion = NewRgn(); |
// get a list of all visible hot spots; here, myHotSpotList is resized (if necessary) to hold |
// a list of the IDs of all visible hot spots |
myHotSpotCount = QTVRGetVisibleHotSpots((**myWindowObject).fInstance, myHotSpotList); |
if (myHotSpotCount > 0) { |
UInt32 *myHotSpotIDPtr = NULL; |
HLock(myHotSpotList); |
myHotSpotIDPtr = (UInt32 *)*myHotSpotList; |
while (myHotSpotCount > 0) { |
// get the next hot spot ID in the list |
myHotSpotID = *myHotSpotIDPtr; |
// get the type of the hot spot |
QTVRGetHotSpotType((**myWindowObject).fInstance, myHotSpotID, &myHotSpotType); |
if (myHotSpotType == kVRMoov_HideHotSpotType) { |
myHotSpotRgn = NewRgn(); |
myErr = QTVRGetHotSpotRegion((**myWindowObject).fInstance, myHotSpotID, myHotSpotRgn); |
if (myErr == noErr) { |
// merge the existing hide region and the region of this hot spot |
MacUnionRgn(myPointer->fHideRegion, myHotSpotRgn, myPointer->fHideRegion); |
} |
DisposeRgn(myHotSpotRgn); |
} |
myHotSpotIDPtr++; |
myHotSpotCount--; |
} |
HUnlock(myHotSpotList); |
} |
if (myHotSpotList != NULL) |
DisposeHandle(myHotSpotList); |
} |
// since we're using an offscreen graphics world, make sure we draw there |
SetGWorld(myPointer->fOffscreenGWorld, GetGWorldDevice(myPointer->fOffscreenGWorld)); |
// set up compositing environment |
GetForeColor(&myColor); |
RGBForeColor(&myPointer->fChromaColor); |
// do the drawing |
if (myPointer->fHideRegion != NULL) |
MacPaintRgn(myPointer->fHideRegion); |
// restore original drawing environment |
RGBForeColor(&myColor); |
// restore original graphics world |
SetGWorld(myBBufGWorld, myBBufGDevice); |
} |
////////// |
// |
// if we're using an offscreen graphics world, copy it into the back buffer |
// |
////////// |
if (myIsDrawing) { |
if (myPointer->fUseOffscreenGWorld) { |
PixMapHandle myPixMap; |
// if anything relevant to DecompressSequenceFrameS has changed, reset the decompression sequence |
if ((myBBufGWorld != myPointer->fPrevBBufGWorld) || !(MacEqualRect(theRect, &myPointer->fPrevBBufRect))) { |
VRMoov_CalcImagingMatrix(myWindowObject, theRect); |
VRMoov_SetupDecompSeq(myPointer, myBBufGWorld); |
} |
myPixMap = GetGWorldPixMap(myPointer->fOffscreenGWorld); |
LockPixels(myPixMap); |
// set the chroma key color, if necessary |
if (myPointer->fCompositeMovie) |
RGBBackColor(&myPointer->fChromaColor); |
// copy the image from the offscreen graphics world into the back buffer |
myErr = DecompressSequenceFrameS( myPointer->fImageSequence, |
#if TARGET_CPU_68K |
StripAddress(GetPixBaseAddr(myPixMap)), |
#else |
GetPixBaseAddr(myPixMap), |
#endif |
(**(myPointer->fImageDesc)).dataSize, |
0, |
NULL, |
NULL); |
// reset the chroma key color; |
// we need to do this because the buffer we just drew into might NOT actually |
// be the real back buffer (see Virtual Reality Programming With QuickTime VR, p. 1-154); |
// the copy between the intermediate buffer and the back buffer respects the current back color. |
if (myPointer->fCompositeMovie) |
RGBBackColor(&kWhiteColor); |
UnlockPixels(myPixMap); |
} |
} |
////////// |
// |
// finish up |
// |
////////// |
// keep track of the GWorld and rectangle passed to us this time |
myPointer->fPrevBBufGWorld = myBBufGWorld; |
myPointer->fPrevBBufRect = *theRect; |
// if we drew something, tell QuickTime VR |
if (myIsDrawing) |
*theFlagsOut = kQTVRBackBufferFlagDidDraw; |
bail: |
HUnlock((Handle)myAppData); |
return(myErr); |
} |
////////// |
// |
// VRMoov_CoverProc |
// The cover function of the embedded movie. |
// |
////////// |
PASCAL_RTN OSErr VRMoov_CoverProc (Movie theMovie, RgnHandle theRegion, SInt32 theRefCon) |
{ |
#pragma unused(theMovie, theRegion, theRefCon) |
return(noErr); |
} |
////////// |
// |
// VRMoov_SetVideoGraphicsMode |
// Set the video media graphics mode of the embedded movie. |
// |
////////// |
void VRMoov_SetVideoGraphicsMode (Movie theMovie, VRScriptMoviePtr theEntry, Boolean theSetVGM) |
{ |
Track myTrack; |
Media myMedia; |
if (theEntry == NULL) |
return; |
myTrack = GetMovieIndTrackType(theMovie, 1, VideoMediaType, movieTrackMediaType | movieTrackEnabledOnly); |
if (myTrack != NULL) { |
myMedia = GetTrackMedia(myTrack); |
if (theSetVGM) |
MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy | transparent, &theEntry->fChromaColor); |
else |
MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy, &kWhiteColor); |
} |
return; |
} |
////////// |
// |
// VRMoov_GetFinishedMovie |
// Get the first enlisted movie that is done playing. |
// |
////////// |
VRScriptMoviePtr VRMoov_GetFinishedMovie (WindowObject theWindowObject) |
{ |
ApplicationDataHdl myAppData; |
VRScriptMoviePtr myPointer = NULL; |
myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject); |
if (myAppData == NULL) |
return(NULL); |
// walk our linked list of movies to find the target movie |
myPointer = (VRScriptMoviePtr)(**myAppData).fListArray[kVREntry_QTMovie]; |
while (myPointer != NULL) { |
if (IsMovieDone(myPointer->fMovie)) |
return(myPointer); |
myPointer = myPointer->fNextEntry; |
} |
return(NULL); |
} |
////////// |
// |
// VRMoov_CheckForCompletedMovies |
// Clean up any movies that are finished playing. |
// |
////////// |
void VRMoov_CheckForCompletedMovies (WindowObject theWindowObject) |
{ |
VRScriptMoviePtr myPointer = NULL; |
// delist any completed movies for the specified movie window |
if (theWindowObject != NULL) |
while ((myPointer = VRMoov_GetFinishedMovie(theWindowObject)) != NULL) |
VRScript_DelistEntry(theWindowObject, (VRScriptGenericPtr)myPointer); |
} |
////////// |
// |
// VRMoov_DumpEntryMem |
// Release any memory associated with the specified list entry. |
// |
////////// |
void VRMoov_DumpEntryMem (VRScriptMoviePtr theEntry) |
{ |
if (theEntry != NULL) { |
if (theEntry->fMovie != NULL) { |
StopMovie(theEntry->fMovie); |
DisposeMovie(theEntry->fMovie); |
} |
if (theEntry->fQTMovieHasVideo) { |
if (theEntry->fOffscreenPixMap != NULL) |
UnlockPixels(theEntry->fOffscreenPixMap); |
if (theEntry->fOffscreenGWorld != NULL) |
DisposeGWorld(theEntry->fOffscreenGWorld); |
if (theEntry->fHideRegion != NULL) |
DisposeRgn(theEntry->fHideRegion); |
VRMoov_RemoveDecompSeq(theEntry); |
if (theEntry->fImageDesc != NULL) |
DisposeHandle((Handle)theEntry->fImageDesc); |
} |
theEntry->fMovie = NULL; |
theEntry->fOffscreenGWorld = NULL; |
theEntry->fPrevBBufGWorld = NULL; |
theEntry->fMediaHandler = NULL; |
theEntry->fHideRegion = NULL; |
theEntry->fImageDesc = NULL; |
free(theEntry->fPathname); |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14