QTVRObjectAuthoring.c

//
//      This is sample code which will make QTVR object movies from Linear QuickTime movies.
//
//      © 1991-1996 Apple Computer, Inc.  All rights reserved.
//
 
 
#include "MakeQTVRObject.h"
#include "extern.h" 
 
//=================================================================================================
// DeleteObjectMovieData1x0
//   -- Delete the QTVR 1.0 object movie data.
//   -- Errors returned:
//          QuickTime errors, Toolbox errors. 
//-------------------------------------------------------------------------------------------------
pascal OSErr DeleteQTVRObjectFileFormat1x0 (
                        Movie       movie,
                        short       movieResFref,
                        short       movieResID,
                        FSSpec      movieSFFile)
{
    UserData    uDat;
    OSErr       err;
    FInfo       finderInfo;
    
    if (movie == nil) return (invalidMovie);
 
    // Remove movie user data
    uDat = GetMovieUserData (movie);
    if ((err = GetMoviesError()) != noErr)
        {
        UserMessage("\pCould not get user data item.");
        return (err);
        }
    RemoveUserData (uDat, 'ctyp', kControllerID);           // Delete special controller
    if ((err = GetMoviesError()) != noErr) 
        {
        UserMessage("\pCould not remove controller type.");
        return (err);
        }
    RemoveUserData (uDat, 'NAVG', 1);                       // Delete object movie data
    if ((err = GetMoviesError()) != noErr)
        {
        UserMessage("\pCould not remove NAVG atom.");
        return (err);
        }
 
    // Remove the file preview
    SetMoviePreviewTime (movie, 0, 0);
    if ((err = GetMoviesError()) != noErr)
        {
        UserMessage("\pCould not set preview time.");
        return (err);
        }
    
    // Change creator type back to MoviePlayer
    err = HGetFInfo (movieSFFile.vRefNum, movieSFFile.parID, movieSFFile.name, &finderInfo);
    if (err != noErr) 
        {
        UserMessage("\pCould not get creator type.");
        return (err);
        }
    finderInfo.fdCreator = kMoviePlayerCreatorType;
    err = HSetFInfo (movieSFFile.vRefNum, movieSFFile.parID, movieSFFile.name, &finderInfo);
    if (err != noErr) 
        {
        UserMessage("\pCould not set creator type.");
        return (err);
        }
    
    // Update the movie file itself
    err = AddFilePreview (movieResFref, 0, nil);
    if (err != noErr)
        {
        UserMessage("\pCould add a file preview.");
        return (err);
        }
    err = UpdateMovieResource (movie, movieResFref, movieResID, 0);
    if (err != noErr)
        {
        UserMessage("\pCould not update movie resource.");
        return (err);
        }
    UpdateResFile (movieResFref);
    if ((err = ResError()) != noErr)
        {
        UserMessage("\pCould not update resource file.");
        return (err);
        }
    
    
    return (noErr);
}
 
 
//=================================================================================================
// DoSetStartUpView
//-------------------------------------------------------------------------------------------------
OSErr DoSetStartUpView (MovieInstance   *theInstance)
{
    OSErr err;
    Movie           movie;
 
    if ( theInstance == nil)
        {
        UserMessage("\pBad instance.");
        return (paramErr);
        }
 
    movie = theInstance->movie;
 
    if (movie == nil) 
        {
        UserMessage("\pBad movie.");
        return (paramErr);
        }
    
    {
        TimeValue   posterViewTime;
        QTVRObjectFileFormat1x0Record   fileFormat;
        err = GetQTVRObjectFileFormat1x0 (
                                movie,
                                &fileFormat);
        posterViewTime = MCGetCurrentTime (theInstance->movieController, nil);
        ConvertTimeToPanUtil (posterViewTime,  
                                fileFormat.frameDuration,
                                fileFormat.numberOfColumns,
                                fileFormat.numberOfRows,
                                fileFormat.loopSize,
                                fileFormat.startHPan,
                                fileFormat.endHPan,
                                fileFormat.startVPan,
                                fileFormat.endVPan,
                                &fileFormat.initialHPan, 
                                &fileFormat.initialVPan);
        gPrefInf.objectInfo.initialVPan = fileFormat.initialVPan;
        gPrefInf.objectInfo.initialHPan = fileFormat.initialHPan;
        err = SetQTVRObjectFileFormat1x0 (
                                    movie,
                                    theInstance->movieResFile,
                                    theInstance->movieResID,
                                    theInstance->spec,
                                    posterViewTime,
                                    &fileFormat);
 
    }
    
    
    return (noErr);
}
 
//=================================================================================================
// StuffQTVRObjectFileFormat1x0
//   -- Error returned:
//          qtParamErr          - if parameter is out of range
//-------------------------------------------------------------------------------------------------
OSErr StuffQTVRObjectFileFormat1x0 (short       movieType,
                                    TimeValue   frameDuration,
                                    short       numberOfColumns,
                                    short       numberOfRows,
                                    short       loopSize,
                                    short       loopTicks,
                                    Fixed       startHPan,
                                    Fixed       endHPan,
                                    Fixed       startVPan,
                                    Fixed       endVPan,
                                    Fixed       fieldOfView,
                                    Fixed       initialHPan,
                                    Fixed       initialVPan,
                                    QTVRObjectFileFormat1x0Ptr  fileFormatPtr)
{
    
    if (numberOfColumns <= 0)
        {
        UserMessage("\pColumns must be > 0.");
        return (qtParamErr);
        }
    if (numberOfRows    <= 0)
        {
        UserMessage("\pRows must be > 0.");
        return (qtParamErr);
        }
    if (loopSize        <= 0)
        {
        UserMessage("\pLoop size must be > 0.");
        return (qtParamErr);
        }
    if (fieldOfView     <= 0)
        {
        UserMessage("\pField of view must be > 0.");
        return (qtParamErr);
        }
    if (startHPan   > endHPan)
        {
        UserMessage("\pEnding HPan must be greater than strarting HPan.");
        return (qtParamErr);
        }
    if (startVPan   < endVPan)
        {
        UserMessage("\pStarting VPan must be greater than ending VPan.");
        return (qtParamErr);
        }
    
        
    fileFormatPtr->reserved1        = 0;                        // For compatibility, always 0
    fileFormatPtr->reserved2        = 0;
    fileFormatPtr->frameDuration    = (short) frameDuration;
    fileFormatPtr->versionNumber    = 1;
    fileFormatPtr->numberOfColumns  = numberOfColumns;
    fileFormatPtr->numberOfRows     = numberOfRows;
    fileFormatPtr->loopSize         = loopSize;
    fileFormatPtr->loopTicks        = loopTicks;
    fileFormatPtr->movieType        = movieType;
    fileFormatPtr->startHPan        = startHPan;
    fileFormatPtr->endHPan          = endHPan;
    fileFormatPtr->startVPan        = startVPan;
    fileFormatPtr->endVPan          = endVPan;
    fileFormatPtr->initialHPan      = initialHPan;
    fileFormatPtr->initialVPan      = initialVPan;
    fileFormatPtr->fieldOfView      = fieldOfView;
    
    return (noErr);
}
 
//=================================================================================================
// SetQTVRObjectMovieData1x0
//-------------------------------------------------------------------------------------------------
pascal OSErr SetQTVRObjectFileFormat1x0 (
                        Movie       movie,
                        short       movieResFref,
                        short       movieResID,
                        FSSpec      movieSFFile,
                        TimeValue   posterViewTime,
                        const QTVRObjectFileFormat1x0Ptr    fileFormatPtr)
{
    OSType      myComponentSubType  = 'stna';
    UserData    uDat                = GetMovieUserData (movie);
    OSErr       err;
    FInfo       finderInfo;
    
    if (movie == nil) return (invalidMovie);
    
    // Save navigable data
    err = SetUserDataItem (uDat, fileFormatPtr, sizeof (QTVRObjectFileFormat1x0Record), 'NAVG', 1);
    if (err != noErr)
        {
        UserMessage("\pCould not set user data item.");
        return (err);
        }
    // Set Controller type to Nav controller
    err = SetUserDataItem (uDat, &myComponentSubType, sizeof (myComponentSubType), 'ctyp', 1);
    if (err != noErr)
        {
        UserMessage("\pCould not set ctype.");
        return (err);
        }
    
    // Set current time to poster view time.
    SetMovieTimeValue (movie, posterViewTime);
 
    // Set the poster time to posterViewTime.  For looping movie, this guarantees
    // that the QT will draw with the key frame first.
    SetMoviePosterTime (movie, posterViewTime);
 
    // Make a movie's preview with duration equal to the animation loop.
    SetMoviePreviewTime (movie, posterViewTime, fileFormatPtr->frameDuration * fileFormatPtr->loopSize);
    
    // Change creator type to QTVRPlayer
    err = HGetFInfo (movieSFFile.vRefNum, movieSFFile.parID, movieSFFile.name, &finderInfo);
    if (err != noErr)
        {
        UserMessage("\pCould not get creator type.");
        return (err);
        }
    finderInfo.fdCreator = kQTVRPlayerCreatorType;
    err = HSetFInfo (movieSFFile.vRefNum, movieSFFile.parID, movieSFFile.name, &finderInfo);
    if (err != noErr)
        {
        UserMessage("\pCould not set creator type.");
        return (err);
        }
    
    // Update the movie file itself
    err = UpdateMovieResource (movie, movieResFref, movieResID, 0);
    if (err != noErr)
        {
        UserMessage("\pCould not update movie resource.");
        return (err);
        }
    UpdateResFile (movieResFref);
    if ((err = ResError()) != noErr)
        {
        UserMessage("\pCould not update resource file.");
        return (err);
        }
    return (noErr);
}
 
//=================================================================================================
// GetQTVRObjectMovieData1x0
//   -- Caller is is responsible to make sure 
//   -- Errors returned:
//          userDataItemNotFound - if QTVR Object file format data is not found 
//          featureUnsupported   - if file format version is not 1.0. 
//-------------------------------------------------------------------------------------------------
pascal OSErr GetQTVRObjectFileFormat1x0 (
                        Movie       movie,
                        QTVRObjectFileFormat1x0Ptr  fileFormatPtr)
{
    OSErr   err;
    
    QTVRObjectFileFormat1x0Record tempFileFormat;
    err = GetUserDataItem (GetMovieUserData (movie), &tempFileFormat, sizeof (QTVRObjectFileFormat1x0Record), 'NAVG', 1);
    if (err != noErr)
        {
        UserMessage("\pCould not get user data. This movie is not an Object movie.");
        return (err);
        }
    if (tempFileFormat.versionNumber != 1)
        {
        UserMessage("\pFeature Unsupported.");
        return (featureUnsupported);
        }
        
    *fileFormatPtr = tempFileFormat;
    return (noErr);
}
 
//=================================================================================================
// Convert from QuickTime time to pan parameters
//-------------------------------------------------------------------------------------------------
void ConvertTimeToPanUtil (TimeValue time, 
                            TimeValue frameDuration,
                            short numColumns,
                            short numRows,
                            short loopSize,
                            Fixed startHPan,
                            Fixed endHPan,
                            Fixed startVPan,
                            Fixed endVPan,
                            Fixed *hPan,
                            Fixed *vPan)
{
    
    short       row, column;
    TimeValue   rc;
    Fixed       panHRange;
    Fixed       panVRange;
    
    panHRange  = endHPan   - startHPan;
    panVRange  = startVPan - endVPan;
 
    time /= frameDuration;              // Adjust for frameDuration
    
    rc = time / loopSize;
    row    = rc / numColumns;
    column = rc % numColumns;
    
    // Note mixed Fixed and integer math. 
    if (numColumns == 1) {
        *hPan = startHPan;
    } else if (panHRange == Long2Fix (360)) {
        *hPan = column * (panHRange / (numColumns  )) + startHPan;
    } else {
        *hPan = column * (panHRange / (numColumns-1)) + startHPan;
    }
    
    if (numRows == 1) {
        *vPan = startVPan;
    } else {
        *vPan = startVPan - row * (panVRange / (numRows-1));
    }
}