home *** CD-ROM | disk | FTP | other *** search
- //////////
- //
- // File: QTUtilities.c
- //
- // Contains: Some utilities for working with QuickTime movies.
- // All utilities start with the prefix "QTUtils_".
- //
- // Written by: Tim Monroe
- // Based heavily on the DTSQTUtilities package by Apple DTS.
- // This began as essentially a subset of that package, revised for cross-platform use.
- //
- // Copyright: ⌐ 1996-1998 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <9> 02/28/98 rtm fixed QTUtils_GetMovieFileLoopingInfo and the like
- // <8> 01/14/98 rtm added QTUtils_ConvertFloatToBigEndian
- // <7> 12/19/97 rtm added QTUtils_AddUserDataTextToMovie and associated routines;
- // added QTUtils_GetMovieFileLoopingInfo and the like
- // <6> 11/06/97 rtm added QTUtils_MakeSampleDescription
- // <5> 10/29/97 rtm modified QTUtils_IsMediaTypeInMovie and similar routines to use GetMovieIndTrackType
- // <4> 10/27/97 rtm added QTUtils_HasQuickTimeVideoEffects
- // <3> 10/17/97 rtm added QTUtils_MovieHasSoundTrack
- // <2> 09/23/97 rtm added endian adjustment to QTUtils_PrintMoviePICT
- // <1> 09/10/97 rtm first file
- //
- //////////
-
- // header files
-
- #ifndef __QTUtilities__
- #include "QTUtilities.h"
-
- #include <sound.h>
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // General utilities.
- //
- // Use these functions to get information about the availability/features of QuickTime or other services.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // QTUtils_IsQuickTimeInstalled
- // Is QuickTime installed?
- //
- //////////
-
- Boolean QTUtils_IsQuickTimeInstalled (void)
- {
- Boolean myQTAvail = false;
- long myAttrs;
- OSErr myErr = noErr;
-
- myErr = Gestalt(gestaltQuickTime, &myAttrs);
- if (myErr == noErr)
- myQTAvail = true;
-
- return(myQTAvail);
- }
-
-
- //////////
- //
- // QTUtils_IsQuickTimeCFMInstalled
- // Are the QuickTime CFM libraries installed?
- //
- //////////
-
- #if TARGET_OS_MAC
- #ifdef powerc
- Boolean QTUtils_IsQuickTimeCFMInstalled (void)
- {
- Boolean myQTCFMAvail = false;
- long myAttrs;
- OSErr myErr = noErr;
-
- // test whether the library is registered.
- myErr = Gestalt(gestaltQuickTimeFeatures, &myAttrs);
- if (myErr == noErr)
- if (myAttrs & (1L << gestaltPPCQuickTimeLibPresent))
- myQTCFMAvail = true;
-
- // test whether a function is available (the library is not moved from the Extension folder);
- // this is the trick to be used when testing if a function is available via CFM
- if (!CompressImage)
- myQTCFMAvail = false;
-
- return(myQTCFMAvail);
- }
- #endif // powerc
- #endif
-
-
- //////////
- //
- // QTUtils_GetQTVersion
- // Get the version of QuickTime installed.
- // The high-order word of the returned long integer contains the version number,
- // so you can test a version like this:
- //
- // if ((QTUtils_GetQTVersion() >> 16) & 0xffff >= 0x0210) // we require QT 2.1 or greater
- // return;
- //
- //////////
-
- long QTUtils_GetQTVersion (void)
- {
- long myVersion = 0L;
- OSErr myErr = noErr;
-
- myErr = Gestalt(gestaltQuickTime, &myVersion);
- if (myErr == noErr)
- return(myVersion);
- else
- return(0L);
- }
-
-
- //////////
- //
- // QTUtils_HasQuickTimeVideoEffects
- // Does the installed version of QuickTime support video effects?
- //
- //////////
-
- Boolean QTUtils_HasQuickTimeVideoEffects (void)
- {
- return(((QTUtils_GetQTVersion() >> 16) & 0xffff) >= kQTVideoEffectsMinVers);
- }
-
-
- //////////
- //
- // QTUtils_HasFullScreenSupport
- // Does the installed version of QuickTime support the full-screen routines?
- //
- //////////
-
- Boolean QTUtils_HasFullScreenSupport (void)
- {
- return(((QTUtils_GetQTVersion() >> 16) & 0xffff) >= kQTFullScreeMinVers);
- }
-
-
- //////////
- //
- // QTUtils_GetMovie
- // Open the specified movie file; if none is specified, query the user to select a file.
- //
- //////////
-
- Movie QTUtils_GetMovie (FSSpec *theFSSpec, short *theRefNum, short *theResID)
- {
- SFTypeList myTypeList = {MovieFileType, 0, 0, 0};
- StandardFileReply myReply;
- Movie myMovie = NULL;
- OSErr myErr = noErr;
-
- // if we are provided with an FSSpec then use it; otherwise elicit a file from the user
- if (theFSSpec == NULL || theFSSpec->vRefNum == 0) {
- StandardGetFilePreview(NULL, 1, myTypeList, &myReply);
- if (!myReply.sfGood)
- return(NULL);
-
- *theFSSpec = myReply.sfFile;
- }
-
- // we should have now a usable FSSpec; just double check this before continuing
- if (theFSSpec == NULL)
- return NULL;
-
- // open the movie file
- myErr = OpenMovieFile(theFSSpec, theRefNum, fsRdPerm);
- if (myErr == noErr) {
- Str255 myMovieName;
- Boolean wasChanged;
-
- *theResID = 0; // we want the first movie
-
- myErr = NewMovieFromFile(&myMovie, *theRefNum, theResID, myMovieName, newMovieActive, &wasChanged);
- CloseMovieFile(*theRefNum);
- }
-
- if (myErr != noErr)
- return(NULL);
- else
- return(myMovie);
- }
-
-
- //////////
- //
- // QTUtils_SaveMovie
- // Save and flatten a movie resource into a file.
- //
- // QTUtils_SaveMovie will provide a user dialog asking for a file name, and will then save the movie
- // into this file. Note that this function will also automatically flatten the movie so that it's
- // self-contained, and also make it cross-platform (by adding any possible resource forks to
- // the end of the data fork). The default name of the movie is also NEWMOVIE.MOV, this reflects
- // the way movie file names should be named for cross-platform support (Windows). The default
- // creator type is also 'TVOD' so that MoviePlayer will be the default application that opens the
- // movie file. If there's an existing movie file with the same name, it will be deleted.
- //
- //////////
-
- OSErr QTUtils_SaveMovie (Movie theMovie)
- {
- StandardFileReply mySFReply;
- OSErr myErr = noErr;
-
- if (theMovie == NULL)
- return(invalidMovie);
-
- StandardPutFile("\pSave Movie as:" , "\pNEWMOVIE.MOV", &mySFReply);
- if (mySFReply.sfGood) {
- FlattenMovieData(theMovie, flattenAddMovieToDataFork, &mySFReply.sfFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, createMovieFileDeleteCurFile);
- myErr = GetMoviesError();
- }
-
- return(myErr);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Media utilities.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // QTUtils_IsMediaTypeInMovie
- // Determine whether a specific media type is in a movie.
- //
- //////////
-
- Boolean QTUtils_IsMediaTypeInMovie (Movie theMovie, OSType theMediaType)
- {
- return(GetMovieIndTrackType(theMovie, 1, theMediaType, movieTrackMediaType | movieTrackEnabledOnly) != NULL);
- }
-
-
- //////////
- //
- // QTUtils_MovieHasSoundTrack
- // Determine whether a movie contains a sound track.
- //
- //////////
-
- Boolean QTUtils_MovieHasSoundTrack (Movie theMovie)
- {
- return(GetMovieIndTrackType(theMovie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly) != NULL);
- }
-
-
- //////////
- //
- // QTUtils_GetSoundMediaHandler
- // Return the sound media handler for a movie.
- //
- //////////
-
- MediaHandler QTUtils_GetSoundMediaHandler (Movie theMovie)
- {
- Track myTrack;
- Media myMedia;
-
- myTrack = GetMovieIndTrackType(theMovie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly);
- if (myTrack != NULL) {
- myMedia = GetTrackMedia(myTrack);
- return(GetMediaHandler(myMedia));
- }
-
- return(NULL);
- }
-
-
- //////////
- //
- // QTUtils_PrintMoviePICT
- // Print the existing movie frame pict.
- //
- // Note that in a real application we should put the PrStlDialog code into the Print Setup╔ menu
- // function. The reason it's inside this function is that we use this code for quick testing of printing.
- //
- //////////
-
- OSErr QTUtils_PrintMoviePICT (Movie theMovie, short x, short y, long PICTUsed)
- {
- PicHandle myPictHandle = NULL;
- THPrint myTHPrint = NULL;
- GrafPtr mySavedPort;
- TPPrPort myPrintPort;
- Boolean myResult;
- Boolean isPrinting = false;
- Rect myPictRect;
- OSErr myErr = noErr;
-
- if (theMovie == NULL)
- return(invalidMovie);
-
- GetPort(&mySavedPort);
-
- // get the PICT to be printed, either the poster pict or the current frame pict.
- switch (PICTUsed) {
- case kPrintFrame:
- myPictHandle = GetMoviePict(theMovie, GetMovieTime(theMovie, 0L));
- break;
-
- case kPrintPoster:
- myPictHandle = GetMoviePosterPict(theMovie);
- break;
-
- default:
- goto Closure;
- }
-
- if (myPictHandle == NULL)
- goto Closure;
-
- #if TARGET_RT_LITTLE_ENDIAN
- // change the fields of the Picture structure,
- // if the target runtime environment uses little-endian format for integers
- (**myPictHandle).picSize = EndianS16_BtoL((**myPictHandle).picSize);
-
- (**myPictHandle).picFrame.top = EndianS16_BtoL((**myPictHandle).picFrame.top);
- (**myPictHandle).picFrame.left = EndianS16_BtoL((**myPictHandle).picFrame.left);
- (**myPictHandle).picFrame.bottom = EndianS16_BtoL((**myPictHandle).picFrame.bottom);
- (**myPictHandle).picFrame.right = EndianS16_BtoL((**myPictHandle).picFrame.right);
- #endif
-
- // get the Print record
- myTHPrint = (THPrint)NewHandleClear(sizeof(TPrint));
- if (myTHPrint == NULL)
- goto Closure;
-
- PrOpen();
- isPrinting = true;
- myErr = PrError();
- if (myErr != noErr)
- goto Closure;
-
- PrintDefault(myTHPrint);
-
- // move this to Print Setup╔ if you want to make this look really cool
- myResult = PrStlDialog(myTHPrint);
- if (!myResult)
- goto Closure;
-
- myResult = PrJobDialog(myTHPrint);
- if (!myResult)
- goto Closure;
-
- myPrintPort = PrOpenDoc(myTHPrint, NULL, NULL);
- PrOpenPage(myPrintPort, NULL);
- myErr = PrError();
- if (myErr != noErr)
- goto Closure;
-
- // print at x,y position
- myPictRect = (*myPictHandle)->picFrame;
- MacOffsetRect(&myPictRect, x - myPictRect.left, y - myPictRect.top);
-
- DrawPicture(myPictHandle, &myPictRect);
-
- // if you want to do additional drawing, do it here.
-
- PrClosePage(myPrintPort);
- PrCloseDoc(myPrintPort);
- myErr = PrError();
- if (myErr != noErr)
- goto Closure;
-
- if ((*myTHPrint)->prJob.bJDocLoop == bSpoolLoop)
- PrPicFile(myTHPrint, NULL, NULL, NULL, NULL);
-
- // our closure handling
- Closure:
- MacSetPort(mySavedPort);
-
- if (isPrinting)
- PrClose();
- if (myPictHandle)
- KillPicture(myPictHandle);
- if (myTHPrint)
- DisposeHandle((Handle)myTHPrint);
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_SelectAllMovie
- // Select the entire movie associated with the specified movie controller.
- //
- //////////
-
- OSErr QTUtils_SelectAllMovie (MovieController theMC)
- {
- TimeRecord myTimeRecord;
- Movie myMovie = NULL;
- OSErr myErr = noErr;
-
- if (theMC == NULL)
- return(paramErr);
-
- myMovie = MCGetMovie(theMC);
- if (myMovie == NULL)
- return(paramErr);
-
- myTimeRecord.value.hi = 0;
- myTimeRecord.value.lo = 0;
- myTimeRecord.base = 0;
- myTimeRecord.scale = GetMovieTimeScale(myMovie);
- myErr = GetMoviesError();
- if (myErr != noErr)
- return(myErr);
-
- myErr = MCDoAction(theMC, mcActionSetSelectionBegin, &myTimeRecord);
- if (myErr != noErr)
- return(myErr);
-
- myTimeRecord.value.lo = GetMovieDuration(myMovie);
- myErr = GetMoviesError();
- if (myErr != noErr)
- return(myErr);
-
- myErr = MCDoAction(theMC, mcActionSetSelectionDuration, &myTimeRecord);
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_MakeSampleDescription
- // Return a new image description with default and specified values.
- //
- //////////
-
- ImageDescriptionHandle QTUtils_MakeSampleDescription (long theEffectType, short theWidth, short theHeight)
- {
- ImageDescriptionHandle mySampleDesc = NULL;
- OSErr myErr = noErr;
-
- // create a new sample description
- mySampleDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
- if (mySampleDesc == NULL)
- return(NULL);
-
- // fill in the fields of the sample description
- (**mySampleDesc).idSize = sizeof(ImageDescription);
- (**mySampleDesc).cType = theEffectType;
- (**mySampleDesc).vendor = kAppleManufacturer;
- (**mySampleDesc).temporalQuality = codecNormalQuality;
- (**mySampleDesc).spatialQuality = codecNormalQuality;
- (**mySampleDesc).width = theWidth;
- (**mySampleDesc).height = theHeight;
- (**mySampleDesc).hRes = 72L << 16;
- (**mySampleDesc).vRes = 72L << 16;
- (**mySampleDesc).dataSize = 0L;
- (**mySampleDesc).frameCount = 1;
- (**mySampleDesc).depth = 24;
- (**mySampleDesc).clutID = -1;
-
- return(mySampleDesc);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // User data utilities.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // QTUtils_AddUserDataTextToMovie
- // Add a user data item, of the specified type, containing the specified text to a movie.
- //
- // This function adds the specified text to the movie's user data;
- // the updated user data is written to the movie file when the movie is next updated
- // (by calling UpdateMovieResource).
- //
- //////////
-
- OSErr QTUtils_AddUserDataTextToMovie (Movie theMovie, char *theText, OSType theType)
- {
- UserData myUserData;
- Handle myHandle;
- short myIndex = 0;
- OSErr myErr = noErr;
-
- // get the movie's user data list
- myUserData = GetMovieUserData(theMovie);
- if (myUserData == NULL)
- return(paramErr);
-
- // copy the specified text into a new handle
- myHandle = NewHandleClear(theText[0]);
- if (myHandle == NULL)
- return(MemError());
-
- BlockMove(&theText[1], *myHandle, theText[0]);
-
- // for simplicity, we assume that we want only one user data item of the specified type in the movie;
- // as a result, we won't worry about overwriting any existing item of that type....
- //
- // if you need multiple user data items of a given type (for example, a copyright notice
- // in several different languages), you would need to modify this code; this is left as an exercise
- // for the reader....
-
- // add the data to the movie's user data
- myErr = AddUserDataText(myUserData, myHandle, theType, myIndex + 1, smSystemScript);
-
- // clean up
- DisposeHandle(myHandle);
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_AddCopyrightToMovie
- // Add a user data item containing the specified copyright text to a movie.
- //
- //////////
-
- OSErr QTUtils_AddCopyrightToMovie (Movie theMovie, char *theText)
- {
- return(QTUtils_AddUserDataTextToMovie(theMovie, theText, kUserDataTextCopyright));
- }
-
-
- //////////
- //
- // QTUtils_AddMovieNameToMovie
- // Add a user data item containing the specified name to a movie.
- //
- //////////
-
- OSErr QTUtils_AddMovieNameToMovie (Movie theMovie, char *theText)
- {
- return(QTUtils_AddUserDataTextToMovie(theMovie, theText, kUserDataTextFullName));
- }
-
-
- //////////
- //
- // QTUtils_AddMovieInfoToMovie
- // Add a user data item containing the specified information to a movie.
- //
- //////////
-
- OSErr QTUtils_AddMovieInfoToMovie (Movie theMovie, char *theText)
- {
- return(QTUtils_AddUserDataTextToMovie(theMovie, theText, kUserDataTextInformation));
- }
-
-
- //////////
- //
- // QTUtils_GetMovieFileLoopingInfo
- // Get the looping state of a movie file.
- //
- // A movie file can have information about its looping state in a user data item of type 'LOOP'.
- // If the movie doesn't contain an item of this type, then we'll assume that it isn't looping.
- // If it does contain an item of this type, then the item data (a long integer) is 0 for normal
- // looping and 1 for palindrome looping. Accordingly, this function returns the following values
- // in the theLoopInfo parameter:
- //
- // 0 == normal looping
- // 1 == palindrome looping
- // 2 == no looping
- //
- //////////
-
- OSErr QTUtils_GetMovieFileLoopingInfo (Movie theMovie, long *theLoopInfo)
- {
- UserData myUserData;
- long myInfo = kNoLooping;
- OSErr myErr = paramErr;
-
- // make sure we've got a movie
- if (theMovie == NULL)
- goto bail;
-
- // get the movie's user data list
- myUserData = GetMovieUserData(theMovie);
- if (myUserData != NULL)
- myErr = GetUserDataItem(myUserData, &myInfo, sizeof(myInfo), FOUR_CHAR_CODE('LOOP'), 0);
-
- bail:
- *theLoopInfo = myInfo;
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_SetMovieFileLoopingInfo
- // Set the looping state for a movie file.
- //
- //////////
-
- OSErr QTUtils_SetMovieFileLoopingInfo (Movie theMovie, long theLoopInfo)
- {
- UserData myUserData;
- short myCount = 0;
- OSErr myErr = paramErr;
-
- // get the movie's user data
- myUserData = GetMovieUserData(theMovie);
- if (myUserData == NULL)
- goto bail;
-
- // we want to end up with at most one user data item of type 'LOOP',
- // so let's remove any existing ones
- myCount = CountUserDataType(myUserData, FOUR_CHAR_CODE('LOOP'));
- while (myCount--)
- RemoveUserData(myUserData, FOUR_CHAR_CODE('LOOP'), 1);
-
- switch (theLoopInfo) {
- case kNormalLooping:
- case kPalindromeLooping:
- myErr = SetUserDataItem(myUserData, &theLoopInfo, sizeof(long), FOUR_CHAR_CODE('LOOP'), 0);
- break;
-
- case kNoLooping:
- default:
- myErr = noErr;
- break;
- }
-
- bail:
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_SetLoopingStateFromFile
- // Set the looping state for a movie based on the looping information in the movie file.
- //
- //////////
-
- OSErr QTUtils_SetLoopingStateFromFile (Movie theMovie, MovieController theMC)
- {
- long myLoopInfo;
- OSErr myErr = noErr;
-
- myErr = QTUtils_GetMovieFileLoopingInfo(theMovie, &myLoopInfo);
- switch (myLoopInfo) {
-
- case kNormalLooping:
- MCDoAction(theMC, mcActionSetLooping, (void *)true);
- MCDoAction(theMC, mcActionSetLoopIsPalindrome, (void *)false);
- break;
-
- case kPalindromeLooping:
- MCDoAction(theMC, mcActionSetLooping, (void *)true);
- MCDoAction(theMC, mcActionSetLoopIsPalindrome, (void *)true);
- break;
-
- case kNoLooping:
- default:
- MCDoAction(theMC, mcActionSetLooping, (void *)false);
- MCDoAction(theMC, mcActionSetLoopIsPalindrome, (void *)false);
- break;
- }
-
- return(myErr);
- }
-
-
- //////////
- //
- // QTUtils_ConvertFloatToBigEndian
- // Convert the specified floating-point number to big-endian format.
- //
- //////////
-
- void QTUtils_ConvertFloatToBigEndian (float *theFloat)
- {
- unsigned long *myLongPtr;
-
- myLongPtr = (unsigned long *)theFloat;
- *myLongPtr = EndianU32_NtoB(*myLongPtr);
- }
-
-
- #endif // ifndef __QTUtilities__