MovieToAIFF.c

/*
    File:       MovieToAIFF.c
 
    Contains:   This app demonstrates how to use Movie Export Component 
                to export QuickTime movie files into AIFF files.    
                1) User interaction.
                2) Export the sound with same quality.
                3) Export the sound to higher quality.
 
    Written by: Larry Lai   
 
    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):
                8/16/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                3/14/95 LL  Add code to check the sound track availability.
                3/13/95 LL  Snippet candidate.
                3/03/95 LL  Created first version.
 
*/
 
#include <Memory.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <StandardFile.h>
#include <ToolUtils.h>
#include <Desk.h>
#include <GestaltEqu.h>
#include <Processes.h>
#include <Movies.h>
#include <QuickTimeComponents.h>
#include <Sound.h>
 
#define     kAboutBox           128
 
#define kMyMBar 128
#define kAboutBoxMenu 129
 
#define movieExportUser 1
#define movieExportSame 2
#define movieExportBest 3
#define fileQuit    5
 
enum {
    menuApple = 128,
    menuFile
};
 
void InitToolbox();
void doMenuItem(long menuChoice);
void exportMovieUser(void);
void exportMovieSame(void);
void exportMovieBest(void);
MovieExportComponent openMovieExportComp(void);
SampleDescriptionHandle scanSoundTracks(Movie theMovie);
 
Boolean     done = false;               //  true if we are ready to quit
Boolean     hasSound = false;
 
void InitToolbox()
{
    InitGraf((Ptr) &qd.thePort);
    InitFonts();
    InitWindows();
    InitMenus();
    FlushEvents(everyEvent,0);
    TEInit();
    InitDialogs(0L);
    InitCursor();
}
 
void main()
{
    OSErr   err;
    long    response;
    EventRecord theEvent;
    short i;
    
    InitToolbox();
    
    MaxApplZone(); 
    
    for(i = 0; i <= 10; i++)
        MoreMasters();
    
    //Does not run under System 6
    Gestalt(gestaltSystemVersion, &response);
    response = (response >> 8) & 0x0f;
    if ( response < 7 ) {
        DebugStr("\pThis Application does not run under System 6!");
        ExitToShell();
    }
    
    // we must have QuickTime around
    if (Gestalt(gestaltQuickTime, &response))
        ExitToShell();
 
    err = EnterMovies();
    if (err) 
        ExitToShell();
 
    SetMenuBar(GetNewMBar(kMyMBar));
    DrawMenuBar();
 
    AppendResMenu(GetMenuHandle(menuApple), 'DRVR');
 
    while (!done){
        SystemTask();
        GetNextEvent(everyEvent, &theEvent);
        switch (theEvent.what) {
            case mouseDown: {
                                short part;
                                WindowPtr whichWindow;
 
                                part = FindWindow(theEvent.where, &whichWindow);
                                switch (part) {
                                    case inMenuBar:
                                                doMenuItem(MenuSelect(theEvent.where));
                                                break;
                                    case inSysWindow:
                                                SystemClick(&theEvent, whichWindow);
                                                break;
                                }
                            }
                            break;
 
            case keyDown: {
                            char c;
 
                            c = theEvent.message & charCodeMask;
                            if (theEvent.modifiers & cmdKey)
                                doMenuItem(MenuKey(c));
                            }
                            break;
 
            default:
                break;
        
        }   
    }
}
 
void doMenuItem(long menuChoice)
{
    short whichMenu = HiWord(menuChoice);
    short whichItem = LoWord(menuChoice);
 
    switch (whichMenu) {
        case menuApple: 
                    if (whichItem > 2) {
                        Str255 daName;
                        
                        GetMenuItemText(GetMenuHandle(menuApple), whichItem, daName);
                        OpenDeskAcc(daName);
                    }
                    else
                        Alert(kAboutBox, nil);
                    break;
 
        case menuFile:  
                    switch (whichItem) {
                        case movieExportUser:
                                    exportMovieUser();
                                    break;
                        case movieExportSame:
                                    exportMovieSame();
                                    break;
                        case movieExportBest:
                                    exportMovieBest();
                                    break;
                        case fileQuit:
                                    done = true;
                                    break;
                    }
                    break;
    }
 
    HiliteMenu(0);
 
    return;
}
 
 
 
void exportMovieUser()
{
    OSErr err = noErr;
    StandardFileReply reply;
    OSType movieType = MovieFileType;
    FSSpec newFile;
    Point where = {100,100};
    ComponentResult result = 0;
    Movie theMovie = nil;
    OSType creator = 0;
    short resRef;
    Boolean canceled = false;
    
    StandardGetFilePreview(nil, 1, &movieType, &reply);
    if (!reply.sfGood) return;
 
    // get the movie.
    OpenMovieFile(&reply.sfFile, &resRef, fsRdPerm);
        NewMovieFromFile(&theMovie, resRef, nil, nil,
                0, nil);
    CloseMovieFile(resRef);
    if (!theMovie) return;
    
    err = ConvertMovieToFile(theMovie, nil,&newFile, 0, 0, -1, nil, 
                            showUserSettingsDialog, 0);
    if (err) {
        DebugStr("\p problems with Convert, may run out of disk space");
        FSpDelete(&newFile);
    }   
}
 
 
void exportMovieSame()
{
    OSErr err = noErr;
    StandardFileReply reply;
    OSType movieType = MovieFileType;
    SFReply putFile;
    FSSpec newFile;
    Str255 newName;
    Point where = {100,100};
    MovieExportComponent exporter = 0;
    SampleDescriptionHandle myDesc = NULL;
    ComponentResult result = 0;
    Movie theMovie = nil;
    OSType creator = 0;
    short resRef;
    Boolean canceled = false;
    OSErr anErr = noErr;
    
    StandardGetFilePreview(nil, 1, &movieType, &reply);
    if (!reply.sfGood) return;
 
    // get the movie.
    OpenMovieFile(&reply.sfFile, &resRef, fsRdPerm);
    NewMovieFromFile(&theMovie, resRef, nil, nil,
                0, nil);
    CloseMovieFile(resRef);
    if (!theMovie) return;
    
    BlockMove(reply.sfFile.name, newName, sizeof(reply.sfFile.name));
    newName[++newName[0]] = '!';
 
    SFPutFile(where, "\pName sound file:", newName, nil, &putFile);
    if (!putFile.good) return;
 
    FSMakeFSSpec(putFile.vRefNum, 0, putFile.fName, &newFile);
 
    myDesc = scanSoundTracks(theMovie);
 
    if(hasSound){
        exporter = openMovieExportComp();
    
        result = MovieExportSetSampleDescription(exporter,myDesc,SoundMediaType); 
    
        if(result)
            DebugStr("\pMovieExportSetSampleDescription error");
 
        err = ConvertMovieToFile(theMovie, nil,&newFile, 'AIFF', 'MAIF', -1, nil, 
                            0, exporter);
                    
        if (err) {
            DebugStr("\p problems with Convert, may run out of disk space");
            FSpDelete(&newFile);
        }   
    
        if(myDesc)
            DisposeHandle((Handle) myDesc);
        
        if(exporter)
            CloseComponent(exporter);
        
        hasSound = false;
 
    }
    else{
        DebugStr("\pCan not find any sound track in the movie.");
        done = true;
    }
        
}
 
 
void exportMovieBest()
{
    OSErr err = noErr;
    StandardFileReply reply;
    OSType movieType = MovieFileType;
    SFReply putFile;
    FSSpec newFile;
    Str255 newName;
    Point where = {100,100};
    MovieExportComponent exporter = 0;
    SampleDescriptionHandle myDesc = NULL;
    ComponentResult result = 0;
    Movie theMovie = nil;
    OSType creator = 0;
    short resRef;
    Boolean canceled = false;
    OSErr anErr = noErr;
    SoundDescriptionHandle  mySoundDesc = nil;
    
    StandardGetFilePreview(nil, 1, &movieType, &reply);
    if (!reply.sfGood) return;
 
    // get the movie.
    OpenMovieFile(&reply.sfFile, &resRef, fsRdPerm);
        NewMovieFromFile(&theMovie, resRef, nil, nil,
                0, nil);
    CloseMovieFile(resRef);
    if (!theMovie) return;
    
    BlockMove(reply.sfFile.name, newName, sizeof(reply.sfFile.name));
    newName[++newName[0]] = '!';
 
    SFPutFile(where, "\pName sound file:", newName, nil, &putFile);
    if (!putFile.good) return;
 
    FSMakeFSSpec(putFile.vRefNum, 0, putFile.fName, &newFile);
    
    // We don't need myDesc here, we just want to know if there is any sound track.
    myDesc = scanSoundTracks(theMovie);
    if(hasSound){
        exporter = openMovieExportComp();
    
        //specify the data format.
        mySoundDesc = (SoundDescriptionHandle)NewHandleClear(sizeof(SoundDescription));
        (**mySoundDesc).descSize = sizeof(SoundDescription);
        (**mySoundDesc).dataFormat = 'twos';
        (**mySoundDesc).dataRefIndex = 1;
        (**mySoundDesc).numChannels = 2;
        (**mySoundDesc).sampleSize = 16;
        (**mySoundDesc).sampleRate = 0xAC440000;    
    
        result = MovieExportSetSampleDescription(exporter,(SampleDescriptionHandle)mySoundDesc,SoundMediaType); 
    
        if(result)
            DebugStr("\pMovieExportSetSampleDescription error");
    
        err = ConvertMovieToFile(theMovie, nil,&newFile, 'AIFF', 'MAIF', -1, nil, 
                            0, exporter);
                    
        if (err) {
            DebugStr("\p problems with Convert, may run out of disk space");
            FSpDelete(&newFile);
        }   
    
        if(myDesc)
            DisposeHandle((Handle) myDesc);
        if(mySoundDesc)
            DisposeHandle((Handle) mySoundDesc);
            
        if(exporter)
            CloseComponent(exporter);
        
        hasSound = false;
    }
    else{
        DebugStr("\pCan not find any sound track in the movie.");
        done = true;
    }
}
 
 
SampleDescriptionHandle scanSoundTracks(Movie theMovie)
{
    short trackCount, index;
    SampleDescriptionHandle aDesc = NULL;
    OSErr   anErr;
    
    //find the first sound track. Since 2.0 all the sound are mixed together.
    trackCount = GetMovieTrackCount(theMovie);
    for(index = 1; index <= trackCount; index++)
    {
        OSType  aTrackType;
        Track   aTrack = NULL;
        Media   aMedia = NULL;
        
        //I did not check error, but you should.
        aTrack = GetMovieIndTrack(theMovie, index); 
        aMedia = GetTrackMedia(aTrack);
        
        GetMediaHandlerDescription(aMedia, &aTrackType, 0, 0);
        if(aTrackType == SoundMediaType)
        {
            hasSound = true;
            aDesc = (SampleDescriptionHandle)NewHandle(sizeof(SampleDescription));
            GetMediaSampleDescription(aMedia, 1, aDesc);
            anErr = GetMoviesError();
            if(anErr != noErr)
            {
                DisposeHandle((Handle)aDesc);
                continue;
            }
        }
    }
    return  aDesc;
    
}
    
MovieExportComponent openMovieExportComp()
{
    MovieExportComponent soundComp;
    Component c;
    ComponentDescription cd;
        
    // specify the export component
    cd.componentType = MovieExportType;
    cd.componentSubType = 'AIFF';
    cd.componentManufacturer = 0;
    cd.componentFlags = canMovieExportFiles;
    cd.componentFlagsMask = canMovieExportFiles;
    c = FindNextComponent(nil, &cd);
 
    if (!c) DebugStr("\pcan not find component");                       // too weird. no export component exists
        soundComp = nil;
    soundComp = OpenComponent(c);
    return  soundComp;
}