_PROGRAMMING QUICKTIME_ by Aaron Walsh [LISTING ONE] /***************************************************************************** * MoviePlayer Application -- This QuickTime program demonstrates how to open a * movie file using a file preview dialog, add a movie controller to the * movie, and play a movie in a window. Author: Aaron E. Walsh * Developed using Think C 5.0, & QuickTime headers ******************************************************************************/ #include #include #include #include #include #include /***** Global Variables ******/ Boolean gSys7Preview; /* is System 7 Preview routine available*/ Movie theMovie; /* info about the movie returned by OpenMovie*/ Rect dispBounds; MovieController myMovieController; /* controller component for movie*/ WindowPtr movieWindow; /* window to play the movie in */ OSErr error; /* Variables used in opening a movie file: */ FSSpec mySpec; /* File System record for System 6 */ short resRefNum; /* Resource reference # of selected file */ SFTypeList ypes = {'MooV'}; /* show files of type 'Moov' */ short numtypes = 1; StandardFileReply fReply; /* Standard File Reply (Sys. 7/QuickTime) */ SFReply oldfReply; /* old style (Sys.6) Standard File Reply */ EventRecord *theEvent; /****** Prototypes ******/ Boolean QuickTimeCapable(void); /* is system QT capable? */ StandardFileReply GetMovie(void); /* user select movie file to play */ void PlayMovie(void); /* play the movie */ void MakeMovieController(void); /* find controller . */ void ShowMovieController(void); /* attach controller */ /***************************************************************************** * main() -- Initialize standard Macintosh toolbox managers, check if QuickTime * is available, execute small loop prompting user for movies to play. Exit * when user selects "Cancel" from preview dialog. *****************************************************************************/ main() { /* Initialize Toolbox Managers and data structures: */ MaxApplZone(); InitGraf(&qd.thePort); FlushEvents(everyEvent, 0); InitWindows(); InitCursor(); if (QuickTimeCapable()) { do { fReply = GetMovie(); /* prompt user for a movie file to play */ if (fReply.sfGood) PlayMovie(); /* play the selected movie. */ } while (fReply.sfGood); ExitMovies(); } else ; /* QuickTime is not available. Normally you would /* put up an error message for user. */ } /**************************************************************************** * GetMovie() -- Allow user to select a movie file to play (file of type * 'Moov') using StandardGetFilePreview routine. *****************************************************************************/ StandardFileReply GetMovie() { Point where; /* for System 6 preview */ if (gSys7Preview) StandardGetFilePreview(0, numtypes, types, &fReply); /* Sys 7 preview dialog */ else { /* using Sys 6 */ where.h = where.v = -2; /* center dialog on screen w/"best" display */ SFGetFilePreview(where, 0l, 0l, numtypes, types, 0l, &oldfReply); fReply.sfGood = oldfReply.good; if (fReply.sfGood) /* convert the reply record into an FSSpec: */ FSMakeFSSpec(oldfReply.vRefNum, 0, oldfReply.fName, &mySpec); } return (fReply); } /**************************************************************************** * MakeMovieController() -- Uses the Component Manager to locate the default * movie controller, where it is then displayed at bottom of movie window. *****************************************************************************/ void MakeMovieController() { Component standardMovieController; ComponentDescription controllerDescription; ComponentResult theErr; Point thePoint; Rect controllerBox; /* Fill in component descriptor fields. This info is used by the * Component Manager to locate a corresponding component. We are * looking for the standard movie controller component: */ controllerDescription.componentType = 'play'; controllerDescription.componentSubType = 0; controllerDescription.componentManufacturer = 0; controllerDescription.componentFlags = 0; controllerDescription.componentFlagsMask = 0; standardMovieController = FindNextComponent( (Component) 0, &controllerDescription); /* Get the controller */ myMovieController = OpenComponent(standardMovieController); if(myMovieController == 0l) return; /* return to caller if this is the case */ /* Place controller in the movie window */ thePoint.h = movieWindow->portRect.left; thePoint.v = movieWindow->portRect.top; theErr = MCNewAttachedController(myMovieController,theMovie, movieWindow, thePoint); if (theErr != 0) return; ShowMovieController(); } /***************************************************************************** * ShowMovieController() -- Adjusts size of movie window so movie and movie * controller are viewable *****************************************************************************/ void ShowMovieController() { Rect movieBox, controllerBox; /* Adjust size of movie window to accomodate both movie and movie controller */ MCGetControllerBoundsRect(myMovieController,&controllerBox); /* Adjust movieBox to accomodate controller: */ UnionRect(&movieBox,&controllerBox,&movieBox); /* Resize movie window: */ SizeWindow( movieWindow,movieBox.right,movieBox.bottom,true); } /**************************************************************************** * PlayMovie() -- Opens the appropriate movie file (file of type 'MooV'), * create a window large enough to fit the movie, and play the movie. *****************************************************************************/ void PlayMovie() { FSSpec movieFSSpec; /* First open the movie file */ if (gSys7Preview) movieFSSpec = fReply.sfFile; else movieFSSpec = mySpec; if ((error = OpenMovieFile(&movieFSSpec, &resRefNum, 0)) != noErr) return; /* if error occured, exit PlayMovie() */ if ((error = NewMovieFromFile( &theMovie,resRefNum, nil, nil,0, nil )) != noErr) return; /* if error occured, exit PlayMovie() */ /* Find movie bounds and set top left to 0,0 so */ /* the movie will be properly postioned in our window */ GetMovieBox(theMovie, &dispBounds); OffsetRect(&dispBounds,-dispBounds.left,-dispBounds.top); SetMovieBox(theMovie, &dispBounds); OffsetRect(&dispBounds,50,50); /* window rect can't hit menu bar */ movieWindow = NewCWindow(0L,&dispBounds,0l,true,0,(WindowPtr)-1L, false,0L); /* window for our movie*/ SetPort(movieWindow); SetMovieGWorld(theMovie,nil,nil); MakeMovieController(); /* routine for creating standard controller */ /* After setup, play the movie: */ GoToBeginningOfMovie(theMovie); /* rewind movie to beginning */ PrerollMovie(theMovie,0,0); /* preload portions of movie */ SetMovieActive(theMovie,true); /* set movie to active for servicing */ /* Use controller to play movie until it is finished. Events are passed to MCIsPlayerEvent which handles controller events: */ while ( !IsMovieDone(theMovie)) { GetNextEvent(everyEvent, theEvent); MCIsPlayerEvent(myMovieController, theEvent); } /* dispose of storage, and return */ DisposeMovie(theMovie); /* movie */ CloseMovieFile(resRefNum); /* reference to movie file */ CloseComponent(myMovieController); /* movie controller */ DisposeWindow(movieWindow); } /**************************************************************************** * QuickTimeCapable() -- Uses Gestalt Manager to check if QuickTime is * available at runtime. If not, return error. *****************************************************************************/ Boolean QuickTimeCapable() { long response; /* Test if QuickTime is available: */ error = Gestalt(gestaltQuickTime, &response); if (error != 0) /* error=0 if OK, else error has occured */ return false; /* if error, return */ /* if no error finding QuickTime, check for ICM so we can use Stand.Preview */ error = Gestalt(gestaltCompressionMgr, &response); if (error != 0) return false; /* Can't use Stand.Preview routines */ error = Gestalt(gestaltStandardFileAttr, &response); if (error != 0) /* if not available, we're playing under System 6 */ gSys7Preview = false; else gSys7Preview = true; /* use System 7 standard preview */ error = EnterMovies(); /* Initialize Movie Toolbox & return result */ if (error != 0) return false; /* error initalizing QuickTime */ else return true; /* QuickTimes available, ready to play movies*/ } [LISTING TWO] /***************************************************************************** * MovieMaker Application -- This QuickTime program demonstrates how to create * a QuickTime movie with associated track and media. The Movie Toolbox, * Component Manager, and Image Compression Manager (ICM) are demonstrated. * Author: Aaron E. Walsh -- Developed using Think C 5.0, & QuickTime headers *****************************************************************************/ #include #include #include #include #include /****** defines ******/ #define kFrameX 150 /* x-coord/width*/ #define kFrameY 125 /* y-coord/height */ #define kPixelDepth 32 /* depth for GWorld */ #define kFrameTotal 30 /* total frames in movie */ #define kTimeScale 15 /* desired frames per second */ #define kFrameRate (Fixed) 1<<16 /* fixed point 1.00 = our frame rate */ /****** Types and globals ******/ /* general: */ OSErr error; Rect frmRect; /* movie file: */ Movie gMovie; /* our movie, */ Track gTrack; /* track, */ Media gMedia; /* and media */ short resRefNum; StandardFileReply fReply; FSSpec movieFSSpec; /* FFSpec reference to movie file */ /* image data: */ char **frameDatabitsH; /* buffer for compressed frames */ ImageDescription **imageDescriptionH;/* image info used by compressor */ PixMap *pixMap,**pixMapH; /* offscreen pixmaps */ /* graphics world: */ GWorldPtr movieGWorld,oldGWorld; /* offscreen grapics worlds */ GDHandle oldGDevice; /* compressor:*/ long compressedFrameSize; /* size of compressed frame */ CodecType codecType; /* desired codec */ CompressorComponent codecID; /* variation of codecType */ short colorDepth; /* depth to compress image to*/ CodecQ imageQuality; /* desired compression quality*/ /* media sample: */ TimeValue sampTime; /* generated when adding sample to media */ /****** Prototypes ******/ void BuildMovie(void); /* main routine to assemble a movie */ void MakeMovieFile(void); /* create movie file and movie itself */ void MakeMovieGWorld(void);/* allocate offscreen graphics environ */ void AllocateMovieBuffer(void); /* allocate storage for frames*/ void MakeMovieFrames(void); /* loop to create all movie frames */ void AddMovieFrame(void); /* compress & add single frame to media*/ void CleanUp(void); /* free allocated storage, make preview */ void main(void); /***************************************************************************** * main() -- Initialize standard Macintosh toolbox managers, check if QuickTime capable and call BuildMovie() to create our movie. ******************************************************************************/ void main(void) { /* Initialize Toolbox Managers and data structures: */ MaxApplZone(); InitGraf(&qd.thePort); FlushEvents(everyEvent, 0); InitWindows(); InitCursor(); if (QuickTimeCapable()) { BuildMovie(); /* create the movie */ } } /***************************************************************************** * BuildMovie() -- Sets up display window for movie frames, and calls * appropriate routines for creating movie. *****************************************************************************/ void BuildMovie(void) { WindowPtr displayWind; Rect windRect; windRect.left = windRect.top = 0; windRect.right = kFrameX; windRect.bottom = kFrameY; OffsetRect(&windRect,150,50); displayWind = NewCWindow(0,&windRect,(StringPtr)"\pMovie Window",true,0, (WindowPtr)-1,true,0); SetPort(displayWind); ClearMoviesStickyError(); /* clear any old movie errors */ while (!GetMoviesStickyError()) { MakeMovieFile(); /*create actual movie file on disk */ MakeMovieGWorld(); /*set up graphics devices for images */ AllocateMovieBuffer(); /*allocate buffer space */ MakeMovieFrames(); /*create, compress & add frames */ CleanUp(); /* create preview & release storage */ } CloseWindow(displayWind); /* close display window */ } /***************************************************************************** * MakeMovieFile() -- Create a new movie file (gMovie) with associated track * (gTrack) and media (gMedia). *****************************************************************************/ void MakeMovieFile(void) { /* StandardPutFile prompt; create movie file */ StandardPutFile((StringPtr) "\pCreate Movie File:", (StringPtr)"\pNew Movie",&fReply); if (!fReply.sfGood) return; movieFSSpec = fReply.sfFile; /* reference to our movie file*/ error = CreateMovieFile( &movieFSSpec,'MPLA',0,createMovieFileDeleteCurFile, &resRefNum,&gMovie); if (error) ExitToShell(); /* Create track and media */ gTrack = NewMovieTrack(gMovie,(long)kFrameX<<16,(long)kFrameY<<16,0); error = GetMoviesError(); if (error) ExitToShell(); gMedia = NewTrackMedia(gTrack, VideoMediaType, kTimeScale, nil,(OSType) nil); error = GetMoviesError(); if (error) ExitToShell(); error = BeginMediaEdits( gMedia ); /* needed to add samples to media */ if (error) ExitToShell(); } /***************************************************************************** * MakeMovieGWorld() -- Make a GWorld (offscreen graphics world) for movie. *****************************************************************************/ void MakeMovieGWorld(void) { GetGWorld(&oldGWorld,&oldGDevice);/* save old graphics world/device*/ frmRect.left = frmRect.top = 0; /* setup size of frame*/ frmRect.right = (short)(kFrameX); frmRect.bottom = (short)(kFrameY); /*create movieGWorld: */ error = NewGWorld(&movieGWorld,kPixelDepth,&frmRect,nil,nil,0); if (error) ExitToShell(); /* get handle to pixMap of movieGWorld: */ pixMapH = GetGWorldPixMap(movieGWorld); /* lock offscreen pixMap in memory:*/ LockPixels(pixMapH); /* lock handle to prevent dangling reference:*/ HLock((Handle)pixMapH); pixMap = *pixMapH; /* make pointer (pixMap) to pixel-map*/ } /***************************************************************************** * AllocateMovieBuffer() -- Allocate frame buffer according to our requested * compression level. *****************************************************************************/ void AllocateMovieBuffer(void) { long maxCompressedFrameSize; /* Max size of a compressed frame*/ /* compressor info: */ codecID = anyCodec; codecType = (CodecType) 'rpza'; /* use video compression */ colorDepth = 1; /* compress to 1 bit depth */ imageQuality = codecNormalQuality;/* quality range is 0x100 to 0x300 */ imageDescriptionH = (ImageDescription **)NewHandle( 4 ); /* find needed buffer size: */ error = GetMaxCompressionSize(&pixMap,&frmRect,colorDepth,imageQuality, codecType,codecID,&maxCompressedFrameSize); if (error) ExitToShell(); /* Allocate frame buffer */ frameDatabitsH = NewHandle(maxCompressedFrameSize); if (!frameDatabitsH) ExitToShell(); HLock(frameDatabitsH); /* lock handle to buffer */ } /***************************************************************************** * MakeMovieFrames() -- Create a unique series of movie frames using simple * QuickDraw calls. Compress and add each frame to movie (gMovie). Stop when * max # of frames is reached ****************************************************/ void MakeMovieFrames(void) { long i; /* loop control */ Rect r2, r3; /* rects used in creating graphics image */ for(i = 0; iportBits.baseAddr),&frmRect,&frmRect,0,0); /* compress and add current frame to movie: */ AddMovieFrame(); } } /***************************************************************************** * AddMovieFrame() -- Compress current frame then add it to our movies media. * This is done for each frame. *****************************************************************************/ void AddMovieFrame(void) { /* compress frame: */ error = CompressImage(pixMapH,&frmRect, imageQuality,,codecType imageDescriptionH, StripAddress(*frameDatabitsH) ); compressedFrameSize = (**imageDescriptionH).dataSize; if (error) ExitToShell(); /* add single frame to media:*/ error = AddMediaSample(gMedia, frameDatabitsH, 0L, compressedFrameSize, (TimeValue)1, (SampleDescriptionHandle) imageDescriptionH, 1L, 0, &sampTime); if (error) ExitToShell(); } /***************************************************************************** * QuickTimeCapable() -- Uses the Gestalt Manager to check if QuickTime is * available at runtime. If not, return error. *****************************************************************************/ Boolean QuickTimeCapable() { long response; /* Test if QuickTime is available: */ error = Gestalt(gestaltQuickTime, &response); if (error != 0) /* error=0 if OK, else an error has occured */ return false; /* if error, not QuickTime capable */ /* if no error finding QuickTime, check for the ICM */ error = Gestalt(gestaltCompressionMgr, &response); if (error != 0) return false; error = EnterMovies();/* Initialize Movie Toolbox */ if (error != 0) return false; /* error initalizing QuickTime */ else return true; /* QuickTime capable; ready to play movie */ } /***************************************************************************** * CleanUp() -- Create a new movie file (gMovie) with associated track (gTrack) * and media (gMedia). Return error code if unable to complete process. *****************************************************************************/ void CleanUp() { short resourceId = 1; error = EndMediaEdits( gMedia ); /* finished adding samples */ if (error) ExitToShell(); error = InsertMediaIntoTrack(gTrack,0L,0L,GetMediaDuration(gMedia),kFrameRate); if (error) ExitToShell(); error = AddMovieResource( gMovie, resRefNum, &resourceId, movieFSSpec.name ); if (error) ExitToShell(); error = MakeFilePreview(resRefNum, (ProgressProcRecordPtr) -1); error = CloseMovieFile( resRefNum ); if (error) ExitToShell(); DisposeMovie(gMovie); /* We don't need the movie anymore */ DisposHandle(frameDatabitsH); /* dispose frame buffer memory */ DisposHandle((Handle)imageDescriptionH); /* and other storage: */ DisposeGWorld(movieGWorld); ExitMovies(); }