moviecontrol.c

/*
    File:       moviecontrol.c
 
    Contains:   
 
    Written by: Jason Hodges-Harris 
 
    Copyright:  Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                7/28/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#include <MediaHandlers.h>
 
#ifndef __COLORPICKER__
#include <ColorPicker.h>
#endif
 
#ifndef __MOVIES__
#include <Movies.h>
#endif
 
#ifndef __QDOFFSCREEN__
#include <QDOffscreen.h>
#endif
 
#ifndef __RESOURCES__
#include <Resources.h>
#endif
 
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
 
#ifndef __TYPES__
#include <Types.h>
#endif
 
 
// Program headers
 
#ifndef __CHROMAPPHEADER__
#include "ChromaKeyMovie.h"
#endif
 
 
//  Global Variables
 
 
/* Global GWorld storage for the QuickTime movie.
   If multiple windows are to be implemented, then these
   declarations should be moved into the window document
   structure, as each movie requires 3 offscreen ports*/
 
GWorldPtr           gOffscreenPort,
                    gBackGroundPort,
                    gBackGroundPicture;
PixMapHandle        gMoviePixmap,
                    gBackGndPixmap,
                    gBackGndPictPM;
 
extern RGBColor     kRGBWhite,
                    kRGBBlack,
                    gKeyColor;
 
extern Boolean      gMovieBackGrnd;
extern Boolean      gDone;
extern Boolean      gMovieOpen;
 
 
/* The PlayMovieChroma() function, is called by Open menu item and
   initialises the movie's offscreen environments and window port  */
 
#pragma segment Test
Boolean PlayMovieChroma(void)
{
    PicHandle           thePict;
    GDHandle            oldGDev;
    CWindowPtr          oldPort,
                        theWindow;
    MovieDocHndl        theDocHndl;
    OSErr               theError;
    QDErr               error;
    Rect                theRect;
    Fixed               theData = 0xEFFF;
 
    GetGWorld(&oldPort,&oldGDev);
    thePict = GetPicture(rBackGroundPict);              // load the background picture
    theWindow = OpenCWindow();
    theDocHndl=(MovieDocHndl)GetWRefCon((WindowPtr)theWindow);
    HLock((Handle)theDocHndl);
    theError = LoadOneMovie(theDocHndl);                // load a QuickTime movie
    // Check if the QuickTime movie was successfully loaded.
    if (theError)
    {
        if (theError == kappDefErr)
            DisplayAlert (rGenAlert,rErrMessages,1);
        // return gracefully as cancel button selected or load error occurred
        DisposeHandle((Handle)theDocHndl);
        DisposeWindow((WindowPtr)theWindow);
        return false;
    }
    // get movie frame dimensions
    GetMovieBox((**theDocHndl).theMovie,&theRect);
 
    /* create the offscreen GWorlds to store the background image,
       the current movie frame and the composite image for transferring to the screen */
    
    error = NewGWorld(&gOffscreenPort,0,&theRect,nil,nil,0);
    error |= NewGWorld(&gBackGroundPort,0,&theRect,nil,nil,0);
    error |= NewGWorld(&gBackGroundPicture,1,&(**thePict).picFrame,nil,nil,0);
    // Check if the GWorlds created successfully.
    
    if (error != noErr)
    {
        /* failed to allocate GWorlds, Alert user of 
        problem and exit application as can't continue. */
        DisplayAlert (rGenAlert,rErrMessages,2);
        gDone = true;
        return false;
    }
    /* Get the GWorld PixMaps and lock down the offscreen ports. */
    gMoviePixmap = GetGWorldPixMap(gOffscreenPort);
    gBackGndPixmap = GetGWorldPixMap(gBackGroundPort);
    gBackGndPictPM = GetGWorldPixMap(gBackGroundPicture);
    LockPixels(gMoviePixmap);
    LockPixels(gBackGndPixmap);
    LockPixels(gBackGndPictPM);
    SetGWorld(gBackGroundPicture,nil);
    /* Draw PICT resource into its GWorld. This saves time having
       to reload and draw the PICT for each frame. */
    HLock((Handle)thePict);
    DrawPicture(thePict,&(*gBackGroundPicture).portRect);
    HUnlock((Handle)thePict);
    ReleaseResource((Handle)thePict);
    SetGWorld(oldPort,oldGDev);
    /* Create a movie controller for the movie, get the controller
       dimensions  and its port to that of the visible window */
    (**theDocHndl).theController = 
        NewMovieController((**theDocHndl).theMovie,&theRect,mcTopLeftMovie);
    theError = MCGetControllerBoundsRect((**theDocHndl).theController,&theRect);
    theError = MCSetControllerPort((**theDocHndl).theController,(CGrafPtr)theWindow);
    SetMovieGWorld((**theDocHndl).theMovie,gOffscreenPort,nil);
    SizeWindow((WindowPtr)theWindow,theRect.right,theRect.bottom,true);
    SetWTitle((WindowPtr)theWindow,(**theDocHndl).theFileSpec.name);
    ShowWindow((WindowPtr)theWindow);
    gMovieOpen = true;
    HUnlock((Handle)theDocHndl);
    return true;
}
 
 
/* Simple function to load a QuickTime movie and 
   place the reference into the movie window document*/
 
#pragma segment Test
OSErr   LoadOneMovie(MovieDocHndl theDocH)
{
    StandardFileReply   theMovieFile;
    SFTypeList          myTypes = {MovieFileType};
    OSErr               error;
    short               myMovieResFile;
    Boolean             movieChanged;
    
    StandardGetFilePreview(nil,1,myTypes,&theMovieFile);
    if (theMovieFile.sfGood)
    {
        error = OpenMovieFile(&theMovieFile.sfFile,&myMovieResFile,fsRdPerm);
        if (error == noErr)
        {
            (**theDocH).theMovieResID = 0;  // get first movie
            error = NewMovieFromFile(&(**theDocH).theMovie,myMovieResFile,&(**theDocH).theMovieResID,
                            nil,newMovieActive,&movieChanged);
            if(error == noErr)
            {
                (**theDocH).theFileSpec = theMovieFile.sfFile;
                CloseMovieFile (myMovieResFile);
                return noErr;
            }
        }
        return kappDefErr;  // error loading movie
    }
    return -kappDefErr; // cancel selected
}
 
 
/* When the TransparentColor() function is called,
   it displays the Color Picker and sets the key
   color to the value returned by the Picker */
 
#pragma segment Test
void    TransparentColor()
{
    RGBColor        theNewColor;
    Point           thePoint = {0,0};
    
    // alter the key color if OK selected
    if (GetColor(thePoint,"\pSelect Color",&gKeyColor,&theNewColor))
        gKeyColor = theNewColor;
    return;
}
 
 
/* The SetPlayAllFrames() function is called by the "Play
   every frame" menu item, in the "Movie Options" Menu.
   This calls a movie controller action to */ 
 
#pragma segment Test
Boolean SetPlayAllFrames(Boolean playAllFrames)
{
    MovieDocHndl    theDocH;
    WindowPtr       theWindow;
    ComponentResult theResult;
    
    playAllFrames = !playAllFrames;
    if (gMovieOpen)
    {
        theWindow = FrontWindow();
        theDocH = (MovieDocHndl)GetWRefCon(theWindow);
        if (playAllFrames)
            theResult = MCDoAction((**theDocH).theController,mcActionSetPlayEveryFrame,(Ptr)true);
        else
            theResult = MCDoAction((**theDocH).theController,mcActionSetPlayEveryFrame,(Ptr)false);
        if (theResult != noErr)
            DisplayAlert (rGenAlert,rErrMessages,1);
    }
    return playAllFrames;
}
 
 
#pragma segment Test
Boolean SetLoopMovie(Boolean loopMovie)
{
    MovieDocHndl    theDocH;
    WindowPtr       theWindow;
    ComponentResult theResult;
    
    loopMovie = !loopMovie;
    if (gMovieOpen)
    {
        theWindow = FrontWindow();
        theDocH=(MovieDocHndl)GetWRefCon(theWindow);
        if (loopMovie)
            theResult = MCDoAction((**theDocH).theController,mcActionSetLooping,(Ptr)true);
        else
            theResult = MCDoAction((**theDocH).theController,mcActionSetLooping,(Ptr)false);
        if (theResult !=noErr)
            DisplayAlert (rGenAlert,rErrMessages,1);
    }
    return loopMovie;
}
 
 
#pragma segment Test
void TransparentKeyMode(WindowPtr theWindow)
{
    MovieDocHndl    theDocHndl;
    CGrafPtr        oldPort;
    GDHandle        oldDevice;
    Rect            theRect;
 
    theRect = (*gOffscreenPort).portRect;
    theDocHndl = (MovieDocHndl)GetWRefCon(theWindow);
    GetGWorld(&oldPort,&oldDevice);
    // use CopyBits()to perform croma keying
    SetGWorld(gBackGroundPort,nil);
    RGBForeColor(&kRGBBlack);
    RGBBackColor(&kRGBWhite);
    CopyBits((BitMap*)(*gBackGndPictPM),
        (BitMap*)(*gBackGndPixmap),
        &(*gBackGroundPicture).portRect,&theRect,srcCopy,nil);
    if (gMovieBackGrnd)
    {
        SetGWorld(gOffscreenPort,nil);
        RGBForeColor(&kRGBBlack);
        RGBBackColor(&gKeyColor);
        CopyBits((BitMap*)(*gBackGndPixmap),
            (BitMap*)(*gMoviePixmap),
            &theRect,&theRect,transparent,nil);
        SetGWorld((CWindowPtr)theWindow,oldDevice);
        RGBForeColor(&kRGBBlack);
        RGBBackColor(&kRGBWhite);
        CopyBits((BitMap*)(*gMoviePixmap),
            (BitMap*)&((*theWindow).portBits),
            &theRect,&theRect,srcCopy,nil);
    }
    else
    {
        SetGWorld(gBackGroundPort,nil);
        RGBForeColor(&kRGBBlack);
        RGBBackColor(&gKeyColor);
        CopyBits((BitMap*)(*gMoviePixmap),
            (BitMap*)(*gBackGndPixmap),
            &theRect,&theRect,transparent,nil);
        SetGWorld((CWindowPtr)theWindow,oldDevice);
        RGBForeColor(&kRGBBlack);
        RGBBackColor(&kRGBWhite);
        CopyBits((BitMap*)(*gBackGndPixmap),
            (BitMap*)&((*theWindow).portBits),
            &theRect,&theRect,srcCopy,nil);
    }
    return;
}
 
 
#pragma segment Test
void ModifierTrackMode(WindowPtr theWindow)
{
    MovieDocHndl                        theDocHndl;
    ModifierTrackGraphicsModeRecord     theModifierStruct;
    long                                theTrackIndex,
                                        theTrackCount;
    Track                               theTrack,
                                        theModifierTrack;
    Media                               theMedia;
    QTAtomContainer                     inputMap;
    QTAtom                              inputAtom;
    OSType                              theMediaType,
                                        inputType;
    short                               resRefNum,
                                        count;
    
    if (gMovieOpen)
    {
        theDocHndl = (MovieDocHndl)GetWRefCon(theWindow);
        SetMovieGWorld((**theDocHndl).theMovie,(CGrafPtr)theWindow,nil);
        theTrackCount = GetMovieTrackCount((**theDocHndl).theMovie);
        theModifierStruct.graphicsMode = transparent;
        theModifierStruct.opColor = gKeyColor;
        theModifierTrack = GetMovieIndTrack((**theDocHndl).theMovie,theTrackCount+1);
        // step thru until first video track found
        for (count=1;count <=theTrackCount;count++)
        {
            theTrack = GetMovieIndTrack((**theDocHndl).theMovie,count);
            theMedia = GetTrackMedia(theTrack);
            GetMediaHandlerDescription(theMedia,&theMediaType,nil,nil);
            if (theMediaType == VideoMediaType)
            {
                AddTrackReference(theTrack,theModifierTrack,
                                  kTrackModifierTypeGraphicsMode,&theTrackIndex);
                count = theTrackCount;  // bump track count
            }
            // create and add the input map
            GetMediaInputMap(theMedia,&inputMap);
            QTInsertChild( inputMap, kParentAtomIsContainer, kTrackModifierInput, theTrackIndex,
                  0, 0, nil,&inputAtom);
                  
            QTInsertChild( inputMap, inputAtom, kTrackModifierType, 1, 0, 
                   sizeof(kTrackModifierTypeGraphicsMode), &inputType, nil );
                   
            SetMediaInputMap(theMedia, inputMap );
            QTDisposeAtomContainer(inputMap );
    
        }
        // save changes to movie
        OpenMovieFile(&(**theDocHndl).theFileSpec,&resRefNum,fsRdWrPerm);
        UpdateMovieResource((**theDocHndl).theMovie,resRefNum,(**theDocHndl).theMovieResID,nil);
        CloseMovieFile(resRefNum);
    }
    return;
}
 
 
#pragma segment Test
void VideoGraphicsMode(WindowPtr theWindow, Boolean SetVGM)
{
    MovieDocHndl        theDocHndl;
    long                theTrackCount;
    Media               theMedia;
    Track               movieTrack = nil;
    OSType              theMediaType;
    short               count;
    
    if (gMovieOpen)
    {
        theDocHndl = (MovieDocHndl)GetWRefCon(theWindow);
        SetMovieGWorld((**theDocHndl).theMovie,(CGrafPtr)theWindow,nil);
        theTrackCount = GetMovieTrackCount((**theDocHndl).theMovie);
        for (count=1;count <=theTrackCount;count++)
        {
            movieTrack = GetMovieIndTrack((**theDocHndl).theMovie,count);
            theMedia = GetTrackMedia(movieTrack);
            GetMediaHandlerDescription(theMedia,&theMediaType,nil,nil);
            if (theMediaType == VideoMediaType)
            {
                if (SetVGM)
                {
                    if (MediaSetGraphicsMode(GetMediaHandler(theMedia),transparent,&gKeyColor))
                        DisplayAlert (rGenAlert,rErrMessages,1);
                }
                else if (!SetVGM)
                {
                    if (MediaSetGraphicsMode(GetMediaHandler(theMedia),srcCopy,&kRGBWhite))
                        DisplayAlert (rGenAlert,rErrMessages,1);
                }
            }
        }
    }
    return;
}
 
 
#pragma segment Test
OSErr   DestroyModifierTrack(MovieDocHndl theDocH)
{
    long            theTrackCount;
    Track           theTrack,
                    theModifierTrack;
    Media           theMedia;
    OSType          theMediaType;
    OSErr           theError;
    short           resRefNum,
                    count;
    
    theError = OpenMovieFile(&(**theDocH).theFileSpec,&resRefNum,fsRdWrPerm);
    theTrackCount = GetMovieTrackCount((**theDocH).theMovie);
    theModifierTrack = GetMovieIndTrack((**theDocH).theMovie,theTrackCount);
    theError |= GetMoviesError();
    // step thru until first video track found
    for (count=1;count <=theTrackCount;count++)
    {
        theTrack = GetMovieIndTrack((**theDocH).theMovie,count);
        theMedia = GetTrackMedia(theTrack);
        GetMediaHandlerDescription(theMedia,&theMediaType,nil,nil);
        if (theMediaType == VideoMediaType)
        {
            SetMediaInputMap(theMedia,nil);
            count = theTrackCount;  // bump track count
        }
    }
    theError |= UpdateMovieResource((**theDocH).theMovie,resRefNum,
                                    (**theDocH).theMovieResID,nil);
    CloseMovieFile(resRefNum);
    return theError;
}