Application Files/ComApplication.c

//////////
//
//  File:       ComApplication.c
//
//  Contains:   Application-specific code for VRScript application.
//
//  Written by: Tim Monroe
//              Based on the QTShell code written by Tim Monroe, which in turn was based on the MovieShell
//              code written by Kent Sandvik (Apple DTS). This current version is now very far removed from
//              MovieShell.
//
//  Copyright:  © 1999 by Apple Computer, Inc., all rights reserved.
//
//  Change History (most recent first):
//     
//     <4>      04/01/02    rtm     tweaked QTApp_Idle so fViewHasChanged doesn't trigger redraw if QD3D not available
//     <3>      04/05/00    rtm     removed code to work around Radar bug 2339989
//     <2>      03/22/00    rtm     made changes to get things running under CarbonLib
//     <1>      11/05/99    rtm     first file
//
//////////
 
//////////
//
// header files
//
//////////
 
#include "ComApplication.h"
 
 
//////////
//
// global variables
//
//////////
 
#if TARGET_OS_MAC
AEEventHandlerUPP       gHandleOpenAppAEUPP;                    // UPPs for our Apple event handlers
AEEventHandlerUPP       gHandleOpenDocAEUPP;
AEEventHandlerUPP       gHandlePrintDocAEUPP;
AEEventHandlerUPP       gHandleQuitAppAEUPP;
extern Boolean          gAppInForeground;                       // is our application in the foreground?    
#endif
 
#if TARGET_OS_WIN32
extern HWND             ghWnd;                                  // the MDI frame window; this window has the menu bar
extern LPSTR            gCmdLine;
#endif
 
Boolean                 gQTVRMgrIsPresent = false;              // is the QuickTime VR Manager available?       
long                    gQTVRMgrVersion = 0L;                   // the version of the QuickTime VR Manager (currently unused)
Boolean                 gHasSoundSprockets = false;             // is SoundSprockets available?
unsigned long           gAbsoluteStartingTime = 0L;             // starting time, in ticks
unsigned long           gAbsoluteElapsedTime = 0L;              // total elapsed time, in ticks
unsigned long           gNodeStartingTime = 0L;                 // node starting time, in ticks
unsigned long           gNodeElapsedTime = 0L;                  // node elapsed time, in ticks
 
Boolean                 gHasQuickDraw3D = false;                // is QuickDraw 3D available?
Boolean                 gHasQuickDraw3D15 = false;              // is QuickDraw 3D version 1.5 (or greater) available?
 
Boolean                 gHasQTVideoEffects = false;             // are the QuickTime video effects available?
 
// external variables
extern Boolean          gAppInForeground;                       // is our application in the foreground?    
extern char             gScriptFileName[kMaxFileNameLength];    // the name of the script file
extern MovieController  gPreviousMC;                            // a controller that's been replaced by a call to ReplaceMainMovie              
extern Movie            gPreviousMovie;                         // a movie that's been replaced by a call to ReplaceMainMovie       
extern WindowPtr        gDebugWindow;                           // the verbose mode debug window
 
extern VRScriptPrefsHdl gPreferences;                           // a handle to the global preferences record
extern FSSpec           gAppFSSpec;                             // file specification for the application itself
 
 
//////////
//
// QTApp_Init
// Do any application-specific initialization.
//
// The theStartPhase parameter determines which "phase" of application start-up is executed,
// *before* the MDI frame window is created or *after*. This distinction is relevant only on
// Windows, so on MacOS, you should always use kInitAppPhase_BothPhases.
//
//////////
 
void QTApp_Init (UInt32 theStartPhase)
{
    // do any start-up activities that should occur before the MDI frame window is created
    if (theStartPhase & kInitAppPhase_BeforeCreateFrameWindow) {
 
        // see if the QuickTime video effects are available
        gHasQTVideoEffects = QTUtils_HasQuickTimeVideoEffects();
    
        // make sure that the QuickTime VR Manager is available in the present operating environment;
        // if it is, get its version and initialize it
        if (QTVRUtils_IsQTVRMgrInstalled()) {
            gQTVRMgrIsPresent = true;
            gQTVRMgrVersion = QTVRUtils_GetQTVRVersion();
        
#if TARGET_OS_WIN32
            // initialize the QuickTime VR Manager
            InitializeQTVR();
#endif
        }
    
#if TARGET_OS_MAC
        // make sure that the Apple Event Manager is available; install handlers for required Apple events
        QTApp_InstallAppleEventHandlers();
#endif
 
        VRHash_Init();                  // create the hash table
        VRPrefs_Init();                 // initialize user preferences
        VRSound_Init();                 // initialize sound capabilities
        VRMoov_Init();                  // initialize embedded-movie capabilities
 
#if QD3D_AVAIL
        VR3DObjects_Init();             // initialize 3D object capabilities
#endif
    
        // get the application-launch starting time 
        gAbsoluteStartingTime = TickCount();
        
    }   // end of kInitAppPhase_BeforeCreateFrameWindow
 
    // do any start-up activities that should occur after the MDI frame window is created
    if (theStartPhase & kInitAppPhase_AfterCreateFrameWindow) {
        
#if TARGET_OS_WIN32
        // on Windows, open as *scripts* any text files specified on the command line
        VRScript_OpenCommandLineScriptFile(gCmdLine);   
                                        
        // on Windows, open as *movies* any movie files specified on the command line
        QTFrame_OpenCommandLineMovies(gCmdLine);                                    
#endif
    }   // end of kInitAppPhase_AfterCreateFrameWindow
}
 
 
//////////
//
// QTApp_Stop
// Do any application-specific shut-down.
//
// The theStopPhase parameter determines which "phase" of application shut-down is executed,
// *before* any open movie windows are destroyed or *after*.
//
//////////
 
void QTApp_Stop (UInt32 theStopPhase)
{   
    WindowReference         myWindow;
    WindowObject            myWindowObject;
    
    // do any shut-down activities that should occur before the movie windows are destroyed
    if (theStopPhase & kStopAppPhase_BeforeDestroyWindows) {
 
        // execute any quitting-time commands for all open document windows
        myWindow = QTFrame_GetFrontMovieWindow();
        while (myWindow != NULL) {
        
            myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow);
            if (myWindowObject != NULL) {
                ApplicationDataHdl      myAppData;
            
                myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject);
                if (myAppData != NULL) {
                    VRScriptAtQuitPtr   myPointer;
                    
                    myPointer = (VRScriptAtQuitPtr)(**myAppData).fListArray[kVREntry_QuitCommand];
                    while (myPointer != NULL) {
                        VRScript_ProcessScriptCommandLine(myWindowObject, myPointer->fCommandLine);
                        myPointer = myPointer->fNextEntry;
                    }
                }
            }
            
            myWindow = QTFrame_GetNextMovieWindow(myWindow);
        }
    
        // close the debug window, if it's open
        if (gDebugWindow != NULL) {
            DisposeWindow(gDebugWindow);
            gDebugWindow = NULL;
        }
    }   // end of kStopAppPhase_BeforeDestroyWindows
    
    // do any shut-down activities that should occur after the movie windows are destroyed
    if (theStopPhase & kStopAppPhase_AfterDestroyWindows) {
    
        VRSound_Stop();                 // shut down sound processing
        VRMoov_Stop();                  // shut down embedded-movie capabilities
        VRPrefs_Stop();                 // shut down user preferences
        VRHash_Stop();                  // dispose of our hash table
 
#if QD3D_AVAIL
        VR3DObjects_Stop();             // shut down 3D object capabilities, if enabled
#endif
 
#if TARGET_OS_MAC
        // dispose of routine descriptors for Apple event handlers
        DisposeAEEventHandlerUPP(gHandleOpenAppAEUPP);
        DisposeAEEventHandlerUPP(gHandleOpenDocAEUPP);
        DisposeAEEventHandlerUPP(gHandlePrintDocAEUPP);
        DisposeAEEventHandlerUPP(gHandleQuitAppAEUPP);
#endif
    
#if TARGET_OS_WIN32
        // terminate QuickTime VR Manager
        if (gQTVRMgrIsPresent)
            TerminateQTVR();
#endif
            
    }   // end of kStopAppPhase_AfterDestroyWindows
    
}
 
 
//////////
//
// QTApp_Idle
// Do any processing that can/should occur at idle time.
//
//////////
 
void QTApp_Idle (WindowReference theWindow)
{
    WindowObject        myWindowObject = NULL;
    GrafPtr             mySavedPort;
    //Cursor                myArrow;
    
    GetPort(&mySavedPort);
    MacSetPort(QTFrame_GetPortFromWindowReference(theWindow));
    
    // update our timer global variables; this also happens in DoApplicationEventLoopAction
    gAbsoluteElapsedTime = TickCount() - gAbsoluteStartingTime; 
    gNodeElapsedTime = TickCount() - gNodeStartingTime;
    
    myWindowObject = QTFrame_GetWindowObjectFromWindow(theWindow);
    if (myWindowObject != NULL) {
        MovieController     myMC = NULL;
        ApplicationDataHdl  myAppData = NULL;
        Boolean             myNeedUpdate = false;
    
        myMC = (**myWindowObject).fController;
        if (myMC != NULL) {
            
            // run any idle-time tasks for the movie
            
#if TARGET_OS_MAC
            // restore the cursor to the arrow
            // if it's outside the front movie window or outside the window's visible region
            if (theWindow == QTFrame_GetFrontMovieWindow()) {
                Rect            myRect;
                Point           myPoint;
                RgnHandle       myVisRegion;
                Cursor          myArrow;
                
                GetMouse(&myPoint);
                myVisRegion = NewRgn();
                GetPortVisibleRegion(QTFrame_GetPortFromWindowReference(theWindow), myVisRegion);
                GetWindowPortBounds(theWindow, &myRect);
                if (!MacPtInRect(myPoint, &myRect) || !PtInRgn(myPoint, myVisRegion))
                    MacSetCursor(GetQDGlobalsArrow(&myArrow));
                    
                DisposeRgn(myVisRegion);
            }
#endif // TARGET_OS_MAC
        }
        
        // if the main window contains a QuickTime movie, give it some time
        if ((**myWindowObject).fInstance == NULL)
            MoviesTask((**myWindowObject).fMovie, 0L);
 
        // see whether we need to execute any time-triggered commands
        VRScript_CheckForTimedCommands(myWindowObject);
 
        // see whether we need to execute any angle-triggered commands
        VRScript_CheckForAngleCommands(myWindowObject);
 
        // if any view parameters have changed, we need to update the window        
        myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject);
        if (myAppData != NULL)
#if QD3D_AVAIL
            if ((**myAppData).fViewHasChanged || (**myAppData).fSoundHasChanged) 
#else
            if ((**myAppData).fSoundHasChanged) 
#endif
                myNeedUpdate = true;
                
        // give any embedded QuickTime movies some processor time
        myNeedUpdate |= VRMoov_DoIdle(myWindowObject);
        
        // give any QuickTime video effects some processor time
        if (gHasQTVideoEffects)
            myNeedUpdate |= VREffects_DoIdle(myWindowObject);
        
#if QD3D_AVAIL
        // give 3D animation and texture-mapping some processor time
        if (gHasQuickDraw3D)
            myNeedUpdate |= VR3DObjects_DoIdle(myWindowObject);
#endif
 
        if (myNeedUpdate)
            if ((**myWindowObject).fInstance != NULL)
                QTVRUpdate((**myWindowObject).fInstance, kQTVRCurrentMode);
    }
    
    MacSetPort(mySavedPort);
}
 
 
//////////
//
// QTApp_Draw
// Update the non-movie controller parts of the specified window.
//
//////////
 
void QTApp_Draw (WindowReference theWindow)
{
    GrafPtr                     mySavedPort = NULL;
    GrafPtr                     myWindowPort = NULL;
    WindowPtr                   myWindow = NULL;
    Rect                        myRect;
    
    GetPort(&mySavedPort);
    
    myWindowPort = QTFrame_GetPortFromWindowReference(theWindow);
    myWindow = QTFrame_GetWindowFromWindowReference(theWindow);
    
    if (myWindowPort == NULL)
        return;
        
    MacSetPort(myWindowPort);
    
#if TARGET_API_MAC_CARBON
    GetPortBounds(myWindowPort, &myRect);
#else
    myRect = myWindowPort->portRect;
#endif
 
    BeginUpdate(myWindow);
 
    // erase any part of a movie window that hasn't already been updated
    // by the movie controller
    if (QTFrame_IsMovieWindow(theWindow))
        EraseRect(&myRect);
 
    // ***insert application-specific drawing here***
    
    EndUpdate(myWindow);
    MacSetPort(mySavedPort);
}
 
 
//////////
//
// QTApp_HandleContentClick
// Handle mouse button clicks in the specified window.
//
//////////
 
void QTApp_HandleContentClick (WindowReference theWindow, EventRecord *theEvent)
{
#pragma unused(theWindow, theEvent)
}
 
 
//////////
//
// QTApp_HandleKeyPress
// Handle application-specific key presses.
// Returns true if the key press was handled, false otherwise.
//
//////////
 
Boolean QTApp_HandleKeyPress (char theCharCode)
{
    Boolean         isHandled = true;   // assume we'll handle the key press
    QTVRInstance    myInstance;
    
    // make sure we can safely call the QTVR API
    if (!gQTVRMgrIsPresent)
        return(false);
    
    myInstance = QTFrame_GetQTVRInstanceFromFrontWindow();
    if (myInstance == NULL)
        return(false);
    
    switch (theCharCode) {
        // take keypad keys as a nudge in the appropriate direction
        case '1':   QTVRNudge(myInstance, kQTVRDownLeft);       break;
        case '2':   QTVRNudge(myInstance, kQTVRDown);           break;
        case '3':   QTVRNudge(myInstance, kQTVRDownRight);      break;
        case '4':   QTVRNudge(myInstance, kQTVRLeft);           break;
        case '6':   QTVRNudge(myInstance, kQTVRRight);          break;
        case '7':   QTVRNudge(myInstance, kQTVRUpLeft);         break;
        case '8':   QTVRNudge(myInstance, kQTVRUp);             break;
        case '9':   QTVRNudge(myInstance, kQTVRUpRight);        break;  
        default:
            isHandled = false;
            break;
    }
 
    if (isHandled)
        QTVRUpdate(myInstance, kQTVRCurrentMode);
        
    return(isHandled);
}
 
 
//////////
//
// QTApp_HandleMenu
// Handle selections in the application's menus.
//
// The theMenuItem parameter is a UInt16 version of the Windows "menu item identifier". 
// When called from Windows, theMenuItem is simply the menu item identifier passed to the window procedure.
// When called from MacOS, theMenuItem is constructed like this:
//  *high-order 8 bits == the Macintosh menu ID (1 thru 256)
//  *low-order 8 bits == the Macintosh menu item (sequential from 1 to ordinal of last menu item in menu)
// In this way, we can simplify the menu-handling code. There are, however, some limitations, mainly that
// the menu item identifiers on Windows must be derived from the Mac values. 
//
//////////
 
Boolean QTApp_HandleMenu (UInt16 theMenuItem)
{
    Boolean             myIsHandled = false;            // false => allow caller to process the menu item
 
    if (theMenuItem == IDM_PREFERENCES) {
        VRPrefs_ShowPrefsDialog();
        myIsHandled = true;
    }
        
    return(myIsHandled);
}
 
 
//////////
//
// QTApp_AdjustMenus
// Adjust state of items in the application's menus.
//
// Currently, the Mac application has only one app-specific menu ("Test"); you could change that.
//
//////////
 
void QTApp_AdjustMenus (WindowReference theWindow, MenuReference theMenu)
{
#pragma unused(theWindow)
#if TARGET_OS_MAC
#pragma unused(theMenu)
#endif
    MenuReference       myMenu;
    
#if TARGET_OS_WIN32
    myMenu = theMenu;
#elif TARGET_OS_MAC
    myMenu = GetMenuHandle(kFileMenuResID);
 
    // do not allow the user to close the Debug window
    if (QTFrame_GetFrontAppWindow() == gDebugWindow)
        QTFrame_SetMenuItemState(myMenu, IDM_FILECLOSE, kDisableMenuItem);
 
#endif  // #elif TARGET_OS_MAC
}
 
 
//////////
//
// QTApp_HandleEvent
// Perform any application-specific event loop actions.
//
// Return true to indicate that we've completely handled the event here, false otherwise.
//
//////////
 
Boolean QTApp_HandleEvent (EventRecord *theEvent)
{
#pragma unused(theEvent)
 
    WindowReference     myWindow = NULL;
    WindowObject        myWindowObject = NULL;
    
    // update our timer global variables; this also happens in DoIdle
    gAbsoluteElapsedTime = TickCount() - gAbsoluteStartingTime; 
    gNodeElapsedTime = TickCount() - gNodeStartingTime;
     
    // check for completed sounds and movies in all open movie windows;
    // also run the idle-time processing routine for all open windows
    myWindow = QTFrame_GetFrontMovieWindow();
 
    while (myWindow != NULL) {
        myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow);
        if (myWindowObject != NULL) {
        
            // check for completed sounds and movies
            VRSound_CheckForCompletedSounds(myWindowObject);
            VRMoov_CheckForCompletedMovies(myWindowObject);
        }
 
        myWindow = QTFrame_GetNextMovieWindow(myWindow);
 
    } // while
    
    // see whether we need to dispose of any replaced movie and controller
    if (gPreviousMC != NULL) {
        DisposeMovieController(gPreviousMC);
        gPreviousMC = NULL;
    }
    
    if (gPreviousMovie != NULL) {
        DisposeMovie(gPreviousMovie);
        gPreviousMovie = NULL;
    }
 
    return(false);  // we didn't intercept the event
}
 
 
//////////
//
// QTApp_SetupController
// Configure the movie controller.
//
//////////
 
void QTApp_SetupController (MovieController theMC)
{
    long            myControllerFlags;
    
    // CLUT table use
    MCDoAction(theMC, mcActionGetFlags, &myControllerFlags);
    MCDoAction(theMC, mcActionSetFlags, (void *)(myControllerFlags | mcFlagsUseWindowPalette));
 
    // enable keyboard event handling
    MCDoAction(theMC, mcActionSetKeysEnabled, (void *)true);
    
    // disable drag support
    MCDoAction(theMC, mcActionSetDragEnabled, (void *)false);
}
 
 
//////////
//
// QTApp_SetupWindowObject
// Do any application-specific initialization of the window object.
//
//////////
 
void QTApp_SetupWindowObject (WindowObject theWindowObject)
{
    Track                   myQTVRTrack;
    Movie                   myMovie;
    MovieController         myMC;
    QTVRInstance            myInstance;
    ApplicationDataHdl      myAppData;
        
    //////////
    //
    // initialize
    //
    //////////
 
    if (theWindowObject == NULL)
        return;
 
    // make sure we can safely call the QTVR API
    if (!gQTVRMgrIsPresent)
        return;
 
    // find the QTVR track, if there is one
    myMC = (**theWindowObject).fController;
    myMovie = (**theWindowObject).fMovie;
    if ((myMC == NULL) || (myMovie == NULL))
        return;
 
    myQTVRTrack = QTVRGetQTVRTrack(myMovie, 1);
    QTVRGetQTVRInstance(&myInstance, myQTVRTrack, myMC);
    (**theWindowObject).fInstance = myInstance;
 
    //////////
    //
    // do any application-specific window configuration
    //
    //////////
 
    if (myInstance != NULL) {
        
        // set unit to radians
        QTVRSetAngularUnits(myInstance, kQTVRRadians);
 
        // do window configuration
        myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
        (**theWindowObject).fAppData = (Handle)myAppData;       
        if (myAppData != NULL) {
            
            //////////
            //
            // initialize for special features (sounds, 3D, etc.)
            //
            //////////
    
            // initialize for sounds
            VRSound_InitWindowData(theWindowObject);
 
#if QD3D_AVAIL
            // initialize for 3D objects
            if (gHasQuickDraw3D)
                VR3DObjects_InitWindowData(theWindowObject);
#endif
 
            // initialize for QuickTime video effects
            if (gHasQTVideoEffects)
                VREffects_InitWindowData(theWindowObject);
 
            // initialize for sprites
            VRSprites_InitWindowData(theWindowObject);
 
            // initialize for wired actions
            VRActions_InitWindowData(theWindowObject);
 
            //////////
            //
            // setup QuickTime VR callback routines
            //
            //////////
 
            // allocate a routine descriptor for our prescreen routine                      
            (**myAppData).fPrescreenProc = NewQTVRImagingCompleteUPP(VRScript_PrescreenRoutine);    
 
            // allocate a routine descriptor for our back buffer procedure                      
            (**myAppData).fBackBufferProc = NewQTVRBackBufferImagingUPP(VRScript_BackBufferImagingProc);
    
            // install all the QuickTime VR-related callback procedures
            VRScript_InstallAllQTVRCallbackProcs(myInstance, theWindowObject);
            
            //////////
            //
            // read the command script file
            //
            //////////
 
            // if the user launched the application by dropping a script file onto the application's icon,
            // then we already know the name of the script file to open (it's stored in gScriptFileName);
            // otherwise, look for a script file in the location and with the name dictated by the user's
            // current preferences
            
            if (strlen(gScriptFileName) > 0) {
                VRScript_OpenScriptFile(theWindowObject, gScriptFileName);
                gScriptFileName[0] = '\0';      // clear out gScriptFileName (we're finished with it for now)
            } else {
                char    myScriptName[kMaxFileNameLength];
                FSSpec  myFSSpec;
                
                // set the current directory, based on the user's preferences
                switch ((**gPreferences).fScriptLocType) {
                    case kVRPrefs_PromptUser: {
                        OSType              myTypeList[] = {kScriptFileType};
                        FSSpec              myFSSpec;
                        OSErr               myErr = noErr;
                    
                        myErr = QTFrame_GetOneFileWithPreview(1, (QTFrameTypeListPtr)myTypeList, &myFSSpec, NULL);
                        if (myErr == noErr) {
                            VRScript_SetCurrentDirectory(&myFSSpec);
                            BlockMove(&myFSSpec.name, myScriptName, myFSSpec.name[0]);
                            myScriptName[myFSSpec.name[0]] = '\0';
                        } else {
                            myScriptName[0] = '\0';
                        }
                            
                        break;
                    }
                    
                    case kVRPrefs_DirOfMovieFile:
                        VRScript_SetCurrentDirectory(&(**theWindowObject).fFileFSSpec);
                        break;
 
                    case kVRPrefs_UserSpecifiedPath:
                        FileUtils_MakeFSSpecForAnyFileInDir((**gPreferences).fScriptPathName, &myFSSpec);
                        VRScript_SetCurrentDirectory(&myFSSpec);
                        break;
                        
                    case kVRPrefs_DirOfApplication:
                        VRScript_SetCurrentDirectory(&gAppFSSpec);
                        break;
                        
                    default:
                        break;
                }
                
                // set the script file name, based on the user's preferences
                switch ((**gPreferences).fScriptNameType) {
                    case kVRPrefs_FileNamePlusTXT: {
                        char *myNewName;
                        char *myFileName = QTUtils_ConvertPascalToCString((**theWindowObject).fFileFSSpec.name);
                        
                        myNewName = FileUtils_ChangeFileNameSuffix(myFileName, kScriptFileSuffix);
                        myScriptName[0] = '\0';
                        strcat(myScriptName, myNewName);
                        
                        free(myFileName);
                        free(myNewName);
                        break;
                    }   
                    
                    case kVRPrefs_UserSpecifiedName:
                        BlockMove(&((**gPreferences).fScriptBaseName[1]), myScriptName, (**gPreferences).fScriptBaseName[0]);
                        myScriptName[(**gPreferences).fScriptBaseName[0]] = '\0';
                        break;
                        
                    default:
                        break;
                }
                
                VRScript_OpenScriptFile(theWindowObject, myScriptName);
            }
            
            //////////
            //
            // run some commands
            //
            //////////
            
            // ***TESTING***
            // this is a good place to test out commands without having to read them from a script file
            if (false) {
                //char  myCmdLine1[kMaxCmdLineLength] = "AtTriggerWiredAction   1   -1  clik    60  1   SetPanAngle#10#1";
                //char  myCmdLine2[kMaxCmdLineLength] = "AtTriggerWiredAction   1   -1  entr    5   1   SetPanAngle#-10#1";
                //char  myCmdLine2[kMaxCmdLineLength] = "Set3DObjColor      200      0.0        1.0     1.0     0";
                //char  myCmdLine1[kMaxCmdLineLength] = "AtClickHSID 1 50 -1 1 PlayMovie#100#0.0#0.0#1.0#40.0#0000#0000#0000#1#1#1#1#0#0#90.0#0#3#http://www.apple.com/quicktime/favorites/bbc_world1/bbc_world1.mov";
                //char  myCmdLine3[kMaxCmdLineLength] = "AtClickHSID 1 40 -1 1 MoveScreen#5.0#0.0#0";
                //char  myCmdLine1[kMaxCmdLineLength] = "AtClickSprite 1 -1 2 SetSpriteMatrix#2#1.0#0.0#0.0#0.0#1.0#0.0#140.0#160.0#1.0#0";
                //char  myCmdLine2[kMaxCmdLineLength] = "AtTime 300 1 1 0 0 1    0 ReplaceMainMovie#0#0#0#Meditations:campus.mov";
                //char  myCmdLine2[kMaxCmdLineLength] = "AtClickHS 1 50 -1 1 ReplaceMainMovie#0#2#0#file:///Meditations/WiredSprite.mov";
                //char  myCmdLine2[kMaxCmdLineLength] = "AtClickHS 1 50 -1 1 ReplaceMainMovie#0#0#0#Meditations:OfficePano.mov";
                //char  myCmdLine2[kMaxCmdLineLength] = "AtClickHS 1 50 -1 1 ReplaceMainMovie#0#0#0#Meditations:WiredSprite.mov";
                //char  myCmdLine3[kMaxCmdLineLength] = "AtTime 600 0 -1 0 0 1   0 ReplaceMainMovie#0#0#0#Meditations:Railroad.mov";
                //char  myCmdLine4[kMaxCmdLineLength] = "AtClickHS 1 61 -1 1 ReplaceMainMovie#0#0#0#Meditations:campus.mov";
                //char  myCmdLine3[kMaxCmdLineLength] = "AtClickHS 1 50 -1 1 ReplaceMainMovie#0#0#0#Meditations:Railroad.mov";
                //char  myCmdLine3[kMaxCmdLineLength] = "OpenResourceFile   0           myCursors";
                //char  myCmdLine4[kMaxCmdLineLength] = "AtClickCustomButton    -1  -1  0       Beep";
                //char  myCmdLine4[kMaxCmdLineLength] = "PlaySceneQTMidi 144 1 1.0 0.0 0.0 180.0 0 0 2 myFile.mov";
                
                //VRScript_ProcessScriptCommandLine(theWindowObject, myCmdLine1);
                //VRScript_ProcessScriptCommandLine(theWindowObject, myCmdLine2);
                //VRScript_ProcessScriptCommandLine(theWindowObject, myCmdLine3);
                //VRScript_ProcessScriptCommandLine(theWindowObject, myCmdLine4);
            }
            // ***TESTING***
            
            //////////
            //
            // initialize for the first node
            //
            //////////
            
            (**myAppData).fViewHasChanged = true;
            (**myAppData).fSoundHasChanged = true;
            
            // node-entering procedure is NOT automatically called for the first node, so do it now....
            VRScript_EnteringNodeProc(myInstance, QTVRGetCurrentNodeID(myInstance), (SInt32)theWindowObject);
            
            QTVRUpdate(myInstance, kQTVRCurrentMode);
        }
    }
}
 
 
//////////
//
// QTApp_RemoveWindowObject
// Do any application-specific clean-up of the window object.
//
//////////
 
void QTApp_RemoveWindowObject (WindowObject theWindowObject)
{
    ApplicationDataHdl  myAppData;
    
    myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(theWindowObject);
    if (myAppData == NULL)
        return;
 
    VRSound_DumpWindowData(theWindowObject);
    VRMoov_DumpNodeMovies(theWindowObject);
    VRMoov_DumpSceneMovies(theWindowObject);
 
#if QD3D_AVAIL
    // clean-up after QuickDraw 3D
    if (gHasQuickDraw3D)
        VR3DObjects_DumpWindowData(theWindowObject);
#endif
        
    // clean-up after QuickTime video effects
    if (gHasQTVideoEffects)
        VREffects_DumpWindowData(theWindowObject);
 
    // clean-up sprites
    VRSprites_DumpWindowData(theWindowObject);
 
#if TARGET_OS_MAC
    // get rid of routine descriptors
    DisposeQTVRImagingCompleteUPP((**myAppData).fPrescreenProc);
    DisposeQTVRBackBufferImagingUPP((**myAppData).fBackBufferProc);
#endif
        
    // get rid of linked lists
    VRScript_DeleteAllLists(theWindowObject);
            
    // get rid of window data
    DisposeHandle((Handle)myAppData);
        
    // QTFrame_DestroyMovieWindow in MacFramework.c or QTFrame_MovieWndProc in WinFramework.c
    // releases the window object itself
}
 
 
//////////
//
// QTApp_MCActionFilterProc 
// Intercept some actions for the movie controller.
//
// NOTE: The theRefCon parameter is a handle to a window object record.
//
//////////
 
PASCAL_RTN Boolean QTApp_MCActionFilterProc (MovieController theMC, short theAction, void *theParams, long theRefCon)
{
#pragma unused(theMC)
 
    Boolean                 isHandled = false;
    WindowObject            myWindowObject = NULL;
    ApplicationDataHdl      myAppData = NULL;
    
    if (theMC == NULL)
        return(isHandled);
        
    myWindowObject = (WindowObject)theRefCon;
    if (myWindowObject == NULL)
        return(isHandled);
        
    myAppData = (ApplicationDataHdl)QTFrame_GetAppDataFromWindowObject(myWindowObject);
 
    switch (theAction) {
    
        // handle window resizing
        case  mcActionControllerSizeChanged:
            QTFrame_SizeWindowToMovie(myWindowObject);
            
            // because the window size has changed, 
            // we need to recalculate QD3D camera's aspect ratio and resize the QD3D draw context
#if QD3D_AVAIL
            if ((**myWindowObject).fInstance != NULL)
                if (gHasQuickDraw3D) {
                    VR3DObjects_SetCameraAspectRatio(myWindowObject);                                
                    VR3DObjects_UpdateDrawContext(myWindowObject);                               
                    QTVRUpdate((**myWindowObject).fInstance, kQTVRCurrentMode);
                }
#endif
            break;
            
        // handle idle events
        case mcActionIdle:
            QTApp_Idle((**myWindowObject).fWindow);
            break;
            
        // handle update events
        case mcActionDraw:
            break;
 
        // handle custom controller button clicks
        case mcActionCustomButtonClick:
            // good human interface design would have us track the cursor and process the mouse-down event
            // only if the subsequent mouse-up event occurs inside of the custom button rectangle; however,
            // we have no way of getting the custom button rectangle; so, we just blindly plow on ahead....
            VRScript_CheckForClickCustomButtonCommands(myWindowObject, (EventRecord *)theParams);
            break;
            
        // handle mouse-down events
        case mcActionMouseDown:
            // look for and handle sprite clicks, but only if the movie has a sprite track
            if (myAppData != NULL)
                if ((**myAppData).fMovieHasSprites)
                    isHandled = VRScript_CheckForClickSpriteCommands(myWindowObject, (EventRecord *)theParams);
            break;
            
        // handle wired actions
        case mcActionExecuteAllActionsForQTEvent:
            // look for and handle wired actions, but only if the movie has wired actions
            if (myAppData != NULL)
                if ((**myAppData).fMovieHasActions)
                    isHandled = VRScript_CheckForWiredActionCommands(myWindowObject, (ResolvedQTEventSpecPtr)theParams);
            break;
        
        default:
            break;
            
    }   // switch (theAction)
    
    return(isHandled);  
}
 
 
#if TARGET_OS_MAC
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Apple Event functions.
//
// Use these functions to install handlers for Apple Events and to handle those events.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
//////////
//
// QTApp_InstallAppleEventHandlers 
// Install handlers for Apple Events.
//
//////////
 
void QTApp_InstallAppleEventHandlers (void)
{
    long        myAttrs;
    OSErr       myErr = noErr;
    
    // see whether the Apple Event Manager is available in the present operating environment;
    // if it is, install handlers for the four required Apple Events
    myErr = Gestalt(gestaltAppleEventsAttr, &myAttrs);
    if (myErr == noErr) {
        if (myAttrs & (1L << gestaltAppleEventsPresent)) {
            // create routine descriptors for the Apple event handlers
            gHandleOpenAppAEUPP = NewAEEventHandlerUPP(QTApp_HandleOpenApplicationAppleEvent);
            gHandleOpenDocAEUPP = NewAEEventHandlerUPP(QTApp_HandleOpenDocumentAppleEvent);
            gHandlePrintDocAEUPP = NewAEEventHandlerUPP(QTApp_HandlePrintDocumentAppleEvent);
            gHandleQuitAppAEUPP = NewAEEventHandlerUPP(QTApp_HandleQuitApplicationAppleEvent);
            
            // install the handlers
            AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, gHandleOpenAppAEUPP, 0L, false);
            AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, gHandleOpenDocAEUPP, 0L, false);
            AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, gHandlePrintDocAEUPP, 0L, false);
            AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, gHandleQuitAppAEUPP, 0L, false);
        }
    }
}
        
        
//////////
//
// QTApp_HandleOpenApplicationAppleEvent 
// Handle the open-application Apple Events.
//
//////////
 
PASCAL_RTN OSErr QTApp_HandleOpenApplicationAppleEvent (const AppleEvent *theMessage, AppleEvent *theReply, long theRefcon)         
{
#pragma unused(theMessage, theReply, theRefcon)
    
    // we don't need to do anything special when opening the application
    return(noErr);
}
 
 
//////////
//
// QTApp_HandleOpenDocumentAppleEvent 
// Handle the open-document Apple Events. This is based on Inside Macintosh: IAC, pp. 4-15f.
//
// Here we process an Open Documents AE only for files of type MovieFileType.
//
//////////
 
PASCAL_RTN OSErr QTApp_HandleOpenDocumentAppleEvent (const AppleEvent *theMessage, AppleEvent *theReply, long theRefcon)            
{
#pragma unused(theReply, theRefcon)
 
    long            myIndex;
    long            myItemsInList;
    AEKeyword       myKeyWd;
    AEDescList      myDocList;
    long            myActualSize;
    DescType        myTypeCode;
    FSSpec          myFSSpec;
    OSErr           myIgnoreErr = noErr;
    OSErr           myErr = noErr;
    
    // get the direct parameter and put it into myDocList
    myDocList.dataHandle = NULL;
    myErr = AEGetParamDesc(theMessage, keyDirectObject, typeAEList, &myDocList);
    
    // count the descriptor records in the list
    if (myErr == noErr)
        myErr = AECountItems(&myDocList, &myItemsInList);
    else
        myItemsInList = 0;
    
    // open each specified file
    for (myIndex = 1; myIndex <= myItemsInList; myIndex++)
        if (myErr == noErr) {
            myErr = AEGetNthPtr(&myDocList, myIndex, typeFSS, &myKeyWd, &myTypeCode, (Ptr)&myFSSpec, sizeof(myFSSpec), &myActualSize);
            if (myErr == noErr) {
                FInfo       myFinderInfo;
                
                // verify that the file type is kScriptFileType and the creator is kScriptFileCreator;
                // to do this, get the Finder information
                myErr = FSpGetFInfo(&myFSSpec, &myFinderInfo);  
                if (myErr == noErr) {
                    if ((myFinderInfo.fdType == kScriptFileType) && (myFinderInfo.fdCreator == kScriptFileCreator))
                        // we've got a script file; find the target QTVR movie and open it
                        VRScript_FindAndOpenQTVRMovieFile(&myFSSpec);
                        
                    if (myFinderInfo.fdType == MovieFileType)
                        // we've got a movie file; just open it
                        QTFrame_OpenMovieInWindow(NULL, &myFSSpec);
                }
            }
        }
 
    if (myDocList.dataHandle)
        myIgnoreErr = AEDisposeDesc(&myDocList);
    
    // make sure we open the document in the foreground     
    gAppInForeground = true;
    return(myErr);
}
 
 
//////////
//
// QTApp_HandlePrintDocumentAppleEvent 
// Handle the print-document Apple Events.
//
// NOT YET IMPLEMENTED.
//
//////////
 
PASCAL_RTN OSErr QTApp_HandlePrintDocumentAppleEvent (const AppleEvent *theMessage, AppleEvent *theReply, long theRefcon)           
{
#pragma unused(theMessage, theReply, theRefcon)
 
    return(errAEEventNotHandled);
}
 
 
//////////
//
// QTApp_HandleQuitApplicationAppleEvent 
// Handle the quit-application Apple Events.
//
//////////
 
PASCAL_RTN OSErr QTApp_HandleQuitApplicationAppleEvent (const AppleEvent *theMessage, AppleEvent *theReply, long theRefcon)         
{
#pragma unused(theMessage, theReply, theRefcon)
 
    // close down the entire framework and application
    QTFrame_QuitFramework();
    return(noErr);
}
#endif // TARGET_OS_MAC