BetterFlattenMovie.c

/*
    File:       BetterFlattenMovie.c
    
    Contains:   Patched version of FlattenMovie/FlattenMovieData.
 
    Written by: John Wang
 
    Copyright:  © 1994 by Apple Computer, Inc., all rights reserved.
 
    Change History (most recent first):
 
        <1>     03/14/94    JW      Re-Created for Universal Headers.
 
    To Do:
    
*/
 
#ifdef THINK_C
#define     applec
#endif
 
#include    <Types.h>
#include    <Memory.h>
#include    <QuickDraw.h>
#include    <Palettes.h>
#include    <QDOffscreen.h>
#include    <Errors.h>
#include    <Fonts.h>
#include    <Dialogs.h>
#include    <Windows.h>
#include    <Menus.h>
#include    <Events.h>
#include    <Desk.h>
#include    <DiskInit.h>
#include    <OSUtils.h>
#include    <Resources.h>
#include    <ToolUtils.h>
#include    <AppleEvents.h>
#include    <EPPC.h>
#include    <GestaltEqu.h>
#include    <Processes.h>
#include    <Balloons.h>
#include    <Aliases.h>
#include    <MixedMode.h>
#include    <Scrap.h>
#include    <LowMem.h>
 
#include    <Movies.h>
 
#include    "BetterFlattenMovie.h"
 
/* ------------------------------------------------------------------------- */
 
pascal void BetterFlattenMovie(Movie theMovie, long movieFlattenFlags, 
            FSSpec *theFile, OSType creator, ScriptCode scriptTag,
            long createMovieFileFlags, short *resId, const StringPtr resName)
{
    Movie       tempMovie;
    short       refNum;
    
    tempMovie = BetterFlattenMovieData(theMovie, movieFlattenFlags, 
            theFile, creator, scriptTag, createMovieFileFlags);
 
    if (tempMovie) {
        if (OpenMovieFile(theFile, &refNum, fsRdWrPerm) == noErr) {
            AddMovieResource( tempMovie, refNum, resId, resName);
            CloseMovieFile(refNum);
        }
        DisposeMovie(tempMovie);
    }
}
 
pascal Movie BetterFlattenMovieData(Movie theMovie, long movieFlattenFlags, 
            FSSpec *theFile, OSType creator, ScriptCode scriptTag,
            long createMovieFileFlags)
{
    long        QTfeature;
    long        readLength, writeLength, newFileSize, origFileSize;
    long        origheader[2];
    long        newheader[2];
    Movie       tempMovie;
    short       destRefNum;
 
    if (Gestalt(gestaltQuickTime, &QTfeature))
        return(0);
    
    //  Do patch only if running QuickTime 1.6.X or less.
    if ((QTfeature >> 16) < 0x170) {
        origheader[0] = 0;
        origheader[1] = 0;
        //  If file exists and the file size is greater than 8, then we can
        //  assume a atom header exists.  We will read this header into
        //  memory so that we can restore it after calling QuickTime's
        //  FlattenMovieData.
        if (FSpOpenDF(theFile, fsRdPerm, &destRefNum) == noErr) {
            if (GetEOF(destRefNum, &origFileSize))
                return(nil);
            if (origFileSize >= 8) {
                if (SetFPos(destRefNum, fsFromStart, 0))
                    return(0);
                readLength = 8;
                if (FSRead(destRefNum, &readLength, origheader))
                    return(0);
            }
            FSClose(destRefNum);
        }
    }
    
    //  Call QuickTime's FlattenMovieData.
    tempMovie = FlattenMovieData(theMovie, movieFlattenFlags, theFile, creator, scriptTag, createMovieFileFlags);
 
    //  Do patch only if running QuickTime 1.6.X or less.
    if ((QTfeature >> 16) < 0x170) {
        if (FSpOpenDF(theFile, fsWrPerm, &destRefNum) == noErr) {
            //  Get new header which is always stored at offset 0 of data fork.
            newheader[0] = 0;
            newheader[1] = 0;
            if (GetEOF(destRefNum, &newFileSize))
                return(0);
            if (newFileSize >= 8) {
                if (SetFPos(destRefNum, fsFromStart, 0))
                    return(0);
                readLength = 8;
                if (FSRead(destRefNum, &readLength, newheader))
                    return(0);
            }
            
            //  Write old header back.
            if (newFileSize >= 8) {
                if (SetFPos(destRefNum, fsFromStart, 0))
                    return(0);
                writeLength = 8;
                if (FSWrite(destRefNum, &writeLength, origheader))
                    return(0);
            }
            
            //  Write new header in the right place.
            if (newFileSize > (origFileSize + 8)) {
                if (SetFPos(destRefNum, fsFromStart, origFileSize))
                    return;
                //  If newheader size is not 0, then calculate new header size by
                //      (i) subtracting out the original file size if the newheader size is
                //          larger than the original file size.
                //      (ii) subtracting the original filesize fromt the new filesize if
                //          the header size is less than or equal to the original filesize.
                //          The reason for this is that FlattenMovieData does not calculate
                //          a new header size unless the movie atom is written to the data fork.
                //          Thus, if there is no data fork, then we can assume that the only
                //          atom added is the movie data atom.
                //  If newheader size is equal to 0, then probably there is no movie
                //  atom and the size is simply the size to the end of the file.
                if (newheader[0] != 0) {
                    if (newheader[0] <= origFileSize)
                        newheader[0] = newFileSize - origFileSize;
                    else
                        newheader[0] = newheader[0] - origFileSize;
                }  else
                    newheader[0] = newFileSize - origFileSize;
                writeLength = 8;
                if (FSWrite(destRefNum, &writeLength, newheader))
                    return;
            }
            FlushVol(nil, theFile->vRefNum);
            FSClose(destRefNum);
        }
    }
    
    return(tempMovie);
}
 
/* ------------------------------------------------------------------------- */
 
OSErr CountMoviesInDataFork(FSSpec *theFile, short *count)
{
    long        header[2];
    short       myRefNum;
    long        fileSize, currentLoc, readLength;
    short       doneCounter;
    OSErr       err;
 
    *count = 0;
    if (FSpOpenDF(theFile, fsRdPerm, &myRefNum) == noErr) {
        if (err = GetEOF(myRefNum, &fileSize))
            return(err);
        currentLoc = 0;
        doneCounter = 0;
        while (fileSize > (currentLoc + 8)) {
            if (err = SetFPos(myRefNum, fsFromStart, currentLoc))
                return(err);
            readLength = 8;
            if (err = FSRead(myRefNum, &readLength, header))
                return(err);
            if (header[1] == 'moov')
                doneCounter++;
            currentLoc += header[0];
        }
        *count = doneCounter;
        FSClose(myRefNum);
    } else
        return(err);
    return(noErr);
}
 
OSErr SearchMoviesInDataFork(FSSpec *theFile, short index, long *fileOffset)
{
    long        header[2];
    short       myRefNum;
    long        currentLoc, readLength;
    short       doneCounter;
    OSErr       err;
 
    if (FSpOpenDF(theFile, fsRdPerm, &myRefNum) == noErr) {
        currentLoc = 0;
        doneCounter = index;
        *fileOffset = 0;
        while ((doneCounter > 0)) {
            if (err = SetFPos(myRefNum, fsFromStart, currentLoc))
                return(err);
            readLength = 8;
            if (err = FSRead(myRefNum, &readLength, header))
                return(err);
            if (header[1] == 'moov')
                doneCounter--;
            *fileOffset = currentLoc;
            currentLoc += header[0];
        }
        FSClose(myRefNum);
    } else
        return(err);
    return(noErr);
}