Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
QTDataEx.c
////////// |
// |
// File: QTDataEx.c |
// |
// Contains: Sample code for working with QuickTime's movie importers and exporters (data exchange components). |
// |
// Written by: Tim Monroe |
// |
// Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <7> 05/11/02 rtm fixed type of gValidFileTypes (now a handle) |
// <6> 01/02/02 rtm Carbonized a SetGWorld call in QTDX_MovieProgressProc |
// <5> 04/19/01 rtm added QTDX_SetExportedMovieDimensions |
// <4> 06/02/00 rtm fixed crashing bug in QTDX_MovieProgressProc |
// <3> 03/20/00 rtm made changes to get things running under CarbonLib |
// <2> 03/03/00 rtm finished basic functionality |
// <1> 02/11/00 rtm first file |
// |
// This file contains code that illustrates the most basic ways of using QuickTime's movie importers and exporters. |
// It shows how to import files that are not QuickTime movie files, how to export a movie into any format supported |
// by QuickTime's movie exporters, and how to export a movie as a hinted movie file. It also illustrates how to use |
// a custom movie progress function. |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "QTDataEx.h" |
#include <TCHAR.H> |
////////// |
// |
// global variables |
// |
////////// |
MovieProgressUPP gMovieProgressProcUPP = NULL; // UPP to our custom movie progress dialog box procedure |
ICMProgressUPP gImageProgressProcUPP = NULL; // UPP to our custom image progress dialog box procedure |
UserItemUPP gProgressUserItemProcUPP = NULL; // UPP to our custom progress dialog user item procedure |
Boolean gUserCancelled = false; // did the user cancel a long operation? (Windows only) |
extern short gAppResFile; // file reference number for this application's resource file |
extern Handle gValidFileTypes; // the list of file types that our application can open |
StringPtr gSettingsFileName; // the name of our settings preferences file |
////////// |
// |
// QTDX_ImportAnyNonMovie |
// Let the user browse for any non-movies; import the selected file as a movie. |
// |
////////// |
OSErr QTDX_ImportAnyNonMovie (void) |
{ |
QTFrameFileFilterUPP myFileFilterUPP = NULL; |
QTFrameTypeListPtr myTypeListPtr = NULL; |
short myNumTypes = 0; |
Movie myMovie = NULL; |
FSSpec myFileToConvert; |
FSSpec myConvertedFile; |
StringPtr myPrompt = QTUtils_ConvertCToPascalString(kImportSavePrompt); |
OSErr myErr = noErr; |
#if TARGET_OS_WIN32 |
myTypeListPtr = (QTFrameTypeListPtr)&gValidFileTypes[1]; // [0] is kQTFileTypeMovie |
myNumTypes = (short)(GetPtrSize((Ptr)gValidFileTypes) / sizeof(OSType)) - 1; |
#endif |
// let the user select an openable file from any files that aren't movie files |
myFileFilterUPP = QTFrame_GetFileFilterUPP((ProcPtr)QTDX_FilterFiles); |
myErr = QTFrame_GetOneFileWithPreview(myNumTypes, myTypeListPtr, &myFileToConvert, (void *)myFileFilterUPP); |
if (myErr != noErr) |
goto bail; |
myConvertedFile = myFileToConvert; |
////////// |
// |
// determine whether the selected file needs to be converted into another file before QuickTime can open it; |
// if so, do the conversion; this is necessary only on MacOS, because on Windows QTFrame_GetOneFileWithPreview |
// calls StandardGetFilePreview, which does this all automatically |
// |
////////// |
#if TARGET_OS_MAC |
if (!QTDX_FileCanBeImportedInPlace(&myFileToConvert)) { |
Boolean myIsSelected = false; |
Boolean myIsReplacing = false; |
// display put-file dialog to save the converted file |
QTFrame_PutFile(myPrompt, myFileToConvert.name, &myConvertedFile, &myIsSelected, &myIsReplacing); |
if (!myIsSelected) |
goto bail; |
// delete any existing file of that name |
if (myIsReplacing) { |
myErr = DeleteMovieFile(&myConvertedFile); |
if (myErr != noErr) |
goto bail; |
} |
// import the file into a movie |
myErr = ConvertFileToMovieFile( |
&myFileToConvert, // the file to convert |
&myConvertedFile, // the file to convert it into |
FOUR_CHAR_CODE('TVOD'), // the output file creator |
smSystemScript, // the script |
NULL, |
0L, |
NULL, |
gMovieProgressProcUPP, |
0L); |
} |
#endif |
// now open the (possibly) converted file in a window |
if (myErr == noErr) |
QTFrame_OpenMovieInWindow(NULL, &myConvertedFile); |
bail: |
if (myFileFilterUPP != NULL) |
DisposeNavObjectFilterUPP(myFileFilterUPP); |
free(myPrompt); |
return(myErr); |
} |
////////// |
// |
// QTDX_ExportMovieAsAnyTypeFile |
// Export the specified movie as a file whose type the user selects. |
// |
////////// |
OSErr QTDX_ExportMovieAsAnyTypeFile (Movie theMovie, FSSpec *theFSSpec) |
{ |
FSSpec myFSSpec = *theFSSpec; |
long myFlags = 0L; |
OSErr myErr = noErr; |
myFlags = createMovieFileDeleteCurFile | showUserSettingsDialog | movieFileSpecValid | movieToFileOnlyExport; |
// export the movie into a file |
myErr = ConvertMovieToFile( |
theMovie, // the movie to convert |
NULL, // all tracks in the movie |
&myFSSpec, // the output file |
0L, // the output file type |
FOUR_CHAR_CODE('TVOD'), // the output file creator |
smSystemScript, // the script |
NULL, // no resource ID to be returned |
myFlags, // export flags |
NULL); // no specific export component |
return(myErr); |
} |
////////// |
// |
// QTDX_ExportMovieAsHintedMovie |
// Add a hint track to a QuickTime movie, using the hinter movie export component. |
// |
// The thePromptUser parameter determines whether we display the movie exporter |
// settings dialog box to allow the user to select export options (true) or whether we |
// try to read the export options from an existing preferences file (false). |
// |
////////// |
OSErr QTDX_ExportMovieAsHintedMovie (Movie theMovie, Boolean thePromptUser) |
{ |
ComponentDescription myCompDesc; |
MovieExportComponent myExporter = NULL; |
long myFlags = createMovieFileDeleteCurFile | movieFileSpecValid; |
FSSpec myHintedFile; |
FSSpec myPrefsFile; |
Boolean myIsSelected = false; |
Boolean myIsReplacing = false; |
StringPtr myPrompt = QTUtils_ConvertCToPascalString(kHintedMovieSavePrompt); |
StringPtr myFileName = QTUtils_ConvertCToPascalString(kHintedMovieFileName); |
ComponentResult myErr = badComponentType; |
// get an output file for the hinted movie |
QTFrame_PutFile(myPrompt, myFileName, &myHintedFile, &myIsSelected, &myIsReplacing); |
if (!myIsSelected) { |
myErr = userCanceledErr; |
goto bail; |
} |
if (myIsReplacing) { |
myErr = FSpDelete(&myHintedFile); |
if (myErr != noErr) |
goto bail; |
} |
// find and open a movie export component that can hint a movie file |
myCompDesc.componentType = MovieExportType; |
myCompDesc.componentSubType = MovieFileType; |
myCompDesc.componentManufacturer = FOUR_CHAR_CODE('hint'); |
myCompDesc.componentFlags = 0; |
myCompDesc.componentFlagsMask = 0; |
myExporter = OpenComponent(FindNextComponent(NULL, &myCompDesc)); |
if (myExporter == NULL) |
goto bail; |
// get the preferences file for this application |
QTDX_GetPrefsFileSpec(&myPrefsFile, (void *)&myHintedFile); |
// read existing movie exporter settings from a file; if we aren't going to prompt |
// the user for exporter settings, these stored settings will be used; otherwise, |
// these stored settings will be used as initial values in the settings dialog box |
QTDX_GetExporterSettingsFromFile(myExporter, &myPrefsFile); |
if (thePromptUser && QTDX_ComponentHasUI(MovieExportType, myExporter)) { |
Boolean myCancelled = false; |
// display a dialog box to prompt the user for desired movie exporter settings |
myErr = MovieExportDoUserDialog(myExporter, theMovie, NULL, 0, 0, &myCancelled); |
if (myCancelled) |
goto bail; |
// save the existing settings into our preferences file |
QTDX_SaveExporterSettingsInFile(myExporter, &myPrefsFile); |
} |
// export the movie into a file |
myErr = ConvertMovieToFile( theMovie, // the movie to convert |
NULL, // all tracks in the movie |
&myHintedFile, // the output file |
MovieFileType, // the output file type |
FOUR_CHAR_CODE('TVOD'), // the output file creator |
smSystemScript, // the script |
NULL, // no resource ID to be returned |
myFlags, // conversion flags |
myExporter); // hinter movie export component |
bail: |
// close the movie export component |
if (myExporter != NULL) |
CloseComponent(myExporter); |
free(myPrompt); |
free(myFileName); |
return((OSErr)myErr); |
} |
////////// |
// |
// QTDX_SetExportedMovieDimensions |
// Configure the movie exporter to export to a specific height and width. |
// |
// The basic idea is this: add atoms of type movieExportHeight and movieExportWidth to the |
// video settings atom (which is of type kQTSettingsVideo) in the atom container returned by |
// MovieExportGetSettingsAsAtomContainer; then install the revised atom container by calling |
// MovieExportSetSettingsFromAtomContainer. |
// |
////////// |
OSErr QTDX_SetExportedMovieDimensions (MovieExportComponent theExporter, Fixed theHeight, Fixed theWidth) |
{ |
QTAtomContainer myContainer = NULL; |
QTAtom myVideoSettingsAtom = 0; |
QTAtom mySizeAtom = 0; |
Fixed myHeight, myWidth; |
OSErr myErr = noErr; |
if (theExporter == NULL) |
return(paramErr); |
myErr = MovieExportGetSettingsAsAtomContainer(theExporter, &myContainer); |
if (myContainer != NULL) { |
// see if a video settings atom exists; if not, add one |
myVideoSettingsAtom = QTFindChildByID(myContainer, kParentAtomIsContainer, kQTSettingsVideo, 1, NULL); |
if (myVideoSettingsAtom == 0) |
QTInsertChild(myContainer, kParentAtomIsContainer, kQTSettingsVideo, 1, 0, 0, NULL, &myVideoSettingsAtom); |
if (myVideoSettingsAtom != 0) { |
// add an atom of type movieExportHeight, or replace data of existing atom |
myHeight = EndianU32_NtoB(theHeight); |
mySizeAtom = QTFindChildByID(myContainer, myVideoSettingsAtom, movieExportHeight, 1, NULL); |
if (mySizeAtom != 0) |
myErr = QTSetAtomData(myContainer, mySizeAtom, sizeof(myHeight), &myHeight); |
else |
myErr = QTInsertChild(myContainer, myVideoSettingsAtom, movieExportHeight, 1, 0, sizeof(myHeight), &myHeight, NULL); |
// add an atom of type movieExportWidth, or replace data of existing atom |
myWidth = EndianU32_NtoB(theWidth); |
mySizeAtom = QTFindChildByID(myContainer, myVideoSettingsAtom, movieExportWidth, 1, NULL); |
if (mySizeAtom != 0) |
myErr = QTSetAtomData(myContainer, mySizeAtom, sizeof(myWidth), &myWidth); |
else |
myErr = QTInsertChild(myContainer, myVideoSettingsAtom, movieExportWidth, 1, 0, sizeof(myWidth), &myWidth, NULL); |
} |
myErr = MovieExportSetSettingsFromAtomContainer(theExporter, myContainer); |
QTDisposeAtomContainer(myContainer); |
} |
return(myErr); |
} |
////////// |
// |
// QTDX_FileCanBeImportedInPlace |
// Can the specified file be opened in place (that is, without having |
// to create an intermediate file to hold the converted file data)? |
// |
////////// |
Boolean QTDX_FileCanBeImportedInPlace (FSSpec *theFSSpec) |
{ |
ComponentDescription myCompDesc; |
Component myComponent = NULL; |
Boolean myCanImportInPlace = false; |
OSType mySubType; |
unsigned long myFlags = 0; |
OSErr myErr = noErr; |
#if TARGET_OS_MAC |
FInfo myFileInfo; |
// get the file type of the specified file |
myErr = FSpGetFInfo(theFSSpec, &myFileInfo); |
if (myErr != noErr) |
goto bail; |
mySubType = myFileInfo.fdType; |
#endif |
#if TARGET_OS_WIN32 |
// get the filename extension of the specified file |
myErr = QTGetFileNameExtension(theFSSpec->name, 0L, &mySubType); |
if (myErr != noErr) |
goto bail; |
myFlags = movieImportSubTypeIsFileExtension; |
#endif |
myCompDesc.componentType = MovieImportType; |
myCompDesc.componentSubType = mySubType; |
myCompDesc.componentManufacturer = 0; |
myCompDesc.componentFlags = myFlags; |
myCompDesc.componentFlagsMask = myFlags; |
myComponent = FindNextComponent(NULL, &myCompDesc); |
if (myComponent != NULL) { |
GetComponentInfo(myComponent, &myCompDesc, NULL, NULL, NULL); |
if (myCompDesc.componentFlags & canMovieImportInPlace) |
myCanImportInPlace = true; |
} |
bail: |
return(myCanImportInPlace); |
} |
////////// |
// |
// QTDX_ComponentHasUserInterface |
// Can the specified movie importer or exporter display a settings dialog? |
// |
////////// |
Boolean QTDX_ComponentHasUI (OSType theType, ComponentInstance theComponent) |
{ |
ComponentDescription myCompDesc; |
Boolean myHasUI = false; |
unsigned long myTestFlag; |
OSErr myErr = noErr; |
if (theType == MovieImportType) |
myTestFlag = hasMovieImportUserInterface; |
else if (theType == MovieExportType) |
myTestFlag = hasMovieExportUserInterface; |
else |
return(false); // not a component type we can handle here |
if (theComponent != NULL) { |
GetComponentInfo((Component)theComponent, &myCompDesc, NULL, NULL, NULL); |
if (myCompDesc.componentFlags & myTestFlag) |
myHasUI = true; |
} |
return(myHasUI); |
} |
////////// |
// |
// QTDX_FilterFiles |
// Filter files for a file-opening dialog box. |
// |
// The default behavior here is to accept all files that can be opened by QuickTime, whether directly |
// or using a movie importer or a graphics importer. For present purposes, we exclude movie files (since |
// we are looking for files to import). |
// |
////////// |
#if TARGET_OS_MAC |
PASCAL_RTN Boolean QTDX_FilterFiles (AEDesc *theItem, void *theInfo, void *theCallBackUD, NavFilterModes theFilterMode) |
{ |
#pragma unused(theCallBackUD, theFilterMode) |
NavFileOrFolderInfo *myInfo = (NavFileOrFolderInfo *)theInfo; |
if (gValidFileTypes == NULL) |
QTFrame_BuildFileTypeList(); |
if (theItem->descriptorType == typeFSS) { |
if (!myInfo->isFolder) { |
OSType myType = myInfo->fileAndFolder.fileInfo.finderInfo.fdType; |
OSType *myTypes = (OSType *)*gValidFileTypes; |
long myCount; |
long myIndex; |
// see whether the file type is in the list of file types that our application can open |
// but do not allow movie files |
myCount = GetHandleSize(gValidFileTypes) / sizeof(OSType); |
for (myIndex = 0; myIndex < myCount; myIndex++) |
if ((myType == myTypes[myIndex]) && (myType != kQTFileTypeMovie)) |
return(true); |
// if we got to here, it's a file we cannot open |
return(false); |
} |
} |
// if we got to here, it's a folder or non-HFS object |
return(true); |
} |
#endif |
#if TARGET_OS_WIN32 |
PASCAL_RTN Boolean QTDX_FilterFiles (CInfoPBPtr thePBPtr) |
{ |
Boolean mySuppressItem = true; |
FSSpec myFSSpec; |
FInfo myFileInfo; |
OSErr myErr = noErr; |
if (thePBPtr->hFileInfo.ioFlAttrib & ioDirMask) { |
// it's a directory, so show it in the list |
mySuppressItem = false; |
} else { |
// it's a file, so show it in the list if it's not a movie file |
myErr = FSMakeFSSpec( thePBPtr->hFileInfo.ioVRefNum, |
thePBPtr->hFileInfo.ioFlParID, |
thePBPtr->hFileInfo.ioNamePtr, |
&myFSSpec); |
if (myErr == noErr) { |
FSpGetFInfo(&myFSSpec, &myFileInfo); |
if (myFileInfo.fdType != kQTFileTypeMovie) |
mySuppressItem = false; |
} |
} |
return(mySuppressItem); |
} |
#endif |
////////// |
// |
// QTDX_MovieProgressProc |
// Handle a custom progress dialog box. |
// |
// The theRefCon parameter is a window object; we don't actually use it here, however. |
// |
////////// |
PASCAL_RTN OSErr QTDX_MovieProgressProc (Movie theMovie, short theMessage, short theOperation, Fixed thePercentDone, long theRefcon) |
{ |
#pragma unused(theMovie, theRefcon) |
CGrafPtr mySavedPort = NULL; |
GDHandle mySavedDevice = NULL; |
static DialogPtr myDialog = NULL; |
static ControlHandle myBar = NULL; |
static UInt32 myTicks = 0; |
short myItemKind; |
Handle myItemHandle = NULL; |
Rect myItemRect; |
Rect myEraseRect; |
Str255 myString; |
EventRecord myEvent; |
char myKey; |
OSErr myErr = noErr; |
GetGWorld(&mySavedPort, &mySavedDevice); |
if (myDialog != NULL) |
#if TARGET_API_MAC_CARBON |
SetGWorld(GetDialogPort(myDialog), GetMainDevice()); |
#else |
SetGWorld((CGrafPtr)myDialog, GetMainDevice()); |
#endif |
switch (theMessage) { |
case movieProgressOpen: |
////////// |
// |
// a lengthy operation is about to begin |
// |
////////// |
// display the progress dialog box |
myDialog = GetNewDialog(kProgressDialogResID, NULL, (WindowPtr)-1); |
if (myDialog != NULL) { |
// set the dialog box as the current graphics port |
#if TARGET_API_MAC_CARBON |
SetGWorld(GetDialogPort(myDialog), GetMainDevice()); |
#else |
SetGWorld((CGrafPtr)myDialog, GetMainDevice()); |
#endif |
SetDialogCancelItem(myDialog, kProgressStopButtonItemID); |
// configure the progress bar control |
GetDialogItem(myDialog, kProgressBarItemID, &myItemKind, &myItemHandle, &myItemRect); |
myBar = (ControlHandle)myItemHandle; |
SetControlMinimum(myBar, 0); |
SetControlMaximum(myBar, (SInt16)kProgressBarMaxValue); |
// set the dialog box text that describes the current operation |
GetDialogItem(myDialog, kProgressTextItemID, &myItemKind, &myItemHandle, &myItemRect); |
if ((theOperation > 0) && (theOperation <= progressOpExportMovie)) { |
GetIndString(myString, kOperationsStringsResID, theOperation); |
SetDialogItemText(myItemHandle, myString); |
} |
// set a user-item drawing procedure for the picture rectangle |
GetDialogItem(myDialog, kProgressPictureItemID, &myItemKind, &myItemHandle, &myItemRect); |
SetDialogItem(myDialog, kProgressPictureItemID, myItemKind, (Handle)gProgressUserItemProcUPP, &myItemRect); |
// show the dialog box and draw the picture in the user item rectangle |
MacShowWindow(GetDialogWindow(myDialog)); |
QTDX_ProgressBoxUserItemProcedure(myDialog, kProgressPictureItemID); |
DrawDialog(myDialog); |
myTicks = TickCount(); |
#if TARGET_OS_WIN32 |
// set a dialog callback procedure, to notify our progress proc that the user has cancelled |
SetModelessDialogCallbackProc(myDialog, (QTModelessCallbackUPP)QTDX_ModelessCallback); |
// initialize the global variable that keeps track of whether the user has cancelled; another way |
// to pass info to the callback procedure would be to set the dialog box' refcon using SetWRefCon |
gUserCancelled = false; |
#endif |
} |
break; |
case movieProgressUpdatePercent: |
////////// |
// |
// a lengthy operation is in progress |
// |
////////// |
#if TARGET_OS_WIN32 |
if (gUserCancelled) { |
myErr = userCanceledErr; // stop the operation by returning a non-zero value |
goto bail; |
} |
#endif |
// check to see whether the user wants to cancel the operation; we support user cancelling |
// by (1) clicking the Stop button, (2) pressing the Escape key, or (3) pressing the Command-period |
// key combination |
// get the item information for the Stop button |
GetDialogItem(myDialog, kProgressStopButtonItemID, &myItemKind, &myItemHandle, &myItemRect); |
// check for user clicks in the Stop button |
if (WaitNextEvent(mDownMask, &myEvent, 0, NULL)) { |
GlobalToLocal(&myEvent.where); |
if (TrackControl((ControlHandle)myItemHandle, myEvent.where, NULL)) |
myErr = userCanceledErr; // stop the operation by returning a non-zero value |
} |
// check for user presses on the Escape key or on equivalent key combinations |
if (WaitNextEvent(keyDownMask, &myEvent, 0, NULL)) { |
myKey = myEvent.message & charCodeMask; |
if (myEvent.modifiers & cmdKey) |
if (IsCmdChar(&myEvent, kPeriod)) |
myKey = kEscapeKey; |
if (myKey == kEscapeKey) { |
unsigned long myTicks; |
// simulate a press on the Stop button |
HiliteControl((ControlHandle)myItemHandle, kControlButtonPart); |
Delay(kMyButtonDelay, &myTicks); |
HiliteControl((ControlHandle)myItemHandle, false); |
myErr = userCanceledErr; // stop the operation by returning a non-zero value |
} |
} |
// make sure the thePercentDone is within the expected range |
if ((thePercentDone < 0) || (thePercentDone > fixed1)) |
break; |
// update our progress dialog box |
if (myBar != NULL) { |
// thePercentDone is in the range 0 to fixed1 (0x00000000 to 0x00010000); |
// we need to scale it to lie within the range 0 to kProgressBarMaxValue |
SetControlValue(myBar, (SInt16)Fix2Long(FixMul(thePercentDone, Long2Fix(kProgressBarMaxValue)))); |
} |
// erase the appropriate bottom portion of the picture |
GetDialogItem(myDialog, kProgressPictureItemID, &myItemKind, &myItemHandle, &myItemRect); |
MacSetRect( &myEraseRect, |
myItemRect.left, |
myItemRect.bottom - (SInt16)Fix2Long(FixMul(thePercentDone, Long2Fix(myItemRect.bottom - myItemRect.top))), |
myItemRect.right, |
myItemRect.bottom); |
EraseRect(&myEraseRect); |
// update the estimated time remaining |
GetDialogItem(myDialog, kProgressTimeItemID, &myItemKind, &myItemHandle, &myItemRect); |
QTDX_EstimateRemainingTime(&myItemRect, thePercentDone, TickCount() - myTicks); |
break; |
case movieProgressClose: |
////////// |
// |
// a lengthy operation has completed |
// |
////////// |
// remove our progress dialog box |
if (myDialog != NULL) |
DisposeDialog(myDialog); |
myDialog = NULL; |
myBar = NULL; |
myTicks = 0; |
break; |
} |
bail: |
SetGWorld(mySavedPort, mySavedDevice); |
return(myErr); |
} |
////////// |
// |
// QTDX_ImageProgressProc |
// Handle a custom progress dialog box. |
// |
////////// |
PASCAL_RTN OSErr QTDX_ImageProgressProc (short theMessage, Fixed thePercentDone, long theRefCon) |
{ |
return(QTDX_MovieProgressProc(NULL, theMessage, 0, thePercentDone, theRefCon)); |
} |
////////// |
// |
// QTDX_ProgressBoxUserItemProcedure |
// A user-item procedure to draw a picture in the progress dialog box. |
// |
////////// |
PASCAL_RTN void QTDX_ProgressBoxUserItemProcedure (DialogPtr theDialog, short theItem) |
{ |
short mySavedResFile; |
short myItemKind; |
Handle myItemHandle = NULL; |
Rect myItemRect; |
PicHandle myPicture = NULL; |
OSErr myErr = noErr; |
if (theItem != kProgressPictureItemID) |
return; |
MacSetPort((GrafPtr)GetDialogPort(theDialog)); |
// get the current resource file |
mySavedResFile = CurResFile(); |
// set the application's resource file; |
// otherwise, we'd get the dialog's resources from the current resource file, |
// which might not be the correct one.... |
UseResFile(gAppResFile); |
// read a picture from our resource file |
myPicture = GetPicture(kProgressPictureID); |
if (myPicture == NULL) |
goto bail; |
// get the rectangle surrounding the user item |
GetDialogItem(theDialog, kProgressPictureItemID, &myItemKind, &myItemHandle, &myItemRect); |
// draw the picture into the desired rectangle |
DrawPicture(myPicture, &myItemRect); |
// draw a frame around the picture |
MacInsetRect(&myItemRect, -1, -1); |
MacFrameRect(&myItemRect); |
bail: |
if (myPicture != NULL) |
ReleaseResource((Handle)myPicture); |
// restore the previous resource file |
UseResFile(mySavedResFile); |
} |
#if TARGET_OS_WIN32 |
////////// |
// |
// QTDX_ModelessCallback |
// A callback procedure for our progress dialog box. |
// |
// Here we pass information back to the progress procedure using the global variable gUserCancelled; |
// a better strategy might be to pass a pointer or handle in the dialog box' refcon, which you would |
// retrieve here by calling GetWRefCon. |
// |
////////// |
static void QTDX_ModelessCallback (EventRecord *theEvent, DialogPtr theDialog, short theItemHit) |
{ |
#pragma unused(theEvent, theDialog) |
if (theItemHit == kProgressStopButtonItemID) |
gUserCancelled = true; |
} |
#endif |
////////// |
// |
// QTDX_GetPrefsFileSpec |
// Fill in the specified FSSpec with info about this application's preferences file. |
// |
// The theRefCon parameter is a pointer to some application-specific data, which you |
// might use to find the preferences file; here, we assume it's a pointer to an FSSpec |
// for the output hinted file. We'll specify a preferences file in the same folder as |
// the hinted file that has the name specified by the global variable gSettingsFileName. |
// |
////////// |
OSErr QTDX_GetPrefsFileSpec (FSSpecPtr thePrefsSpecPtr, void *theRefCon) |
{ |
FSSpecPtr myFSSpecPtr = (FSSpecPtr)theRefCon; |
OSErr myErr = noErr; |
if (myFSSpecPtr == NULL) |
return(paramErr); |
myErr = FSMakeFSSpec(myFSSpecPtr->vRefNum, myFSSpecPtr->parID, gSettingsFileName, thePrefsSpecPtr); |
return(myErr); |
} |
////////// |
// |
// QTDX_SaveExporterSettingsInFile |
// Get the current settings of the specified movie exporter and save them into a file. |
// |
////////// |
OSErr QTDX_SaveExporterSettingsInFile (MovieExportComponent theExporter, FSSpecPtr theFSSpecPtr) |
{ |
QTAtomContainer myContainer = NULL; |
ComponentResult myErr = noErr; |
myErr = MovieExportGetSettingsAsAtomContainer(theExporter, &myContainer); |
if (myErr != noErr) |
goto bail; |
myErr = QTDX_WriteHandleToFile((Handle)myContainer, theFSSpecPtr); |
bail: |
if (myContainer != NULL) |
QTDisposeAtomContainer(myContainer); |
return((OSErr)myErr); |
} |
////////// |
// |
// QTDX_GetExporterSettingsFromFile |
// Read the movie exporter settings saved in the specified file. |
// |
////////// |
OSErr QTDX_GetExporterSettingsFromFile (MovieExportComponent theExporter, FSSpecPtr theFSSpecPtr) |
{ |
Handle myHandle = NULL; |
ComponentResult myErr = fnfErr; // assume we cannot find the file |
myHandle = QTDX_ReadHandleFromFile(theFSSpecPtr); |
if (myHandle == NULL) |
goto bail; |
myErr = MovieExportSetSettingsFromAtomContainer(theExporter, (QTAtomContainer)myHandle); |
bail: |
if (myHandle != NULL) |
DisposeHandle(myHandle); |
return((OSErr)myErr); |
} |
////////// |
// |
// QTDX_WriteHandleToFile |
// Write the data in the specified handle into the specified file; |
// if the file already exists, it is overwritten. |
// |
////////// |
OSErr QTDX_WriteHandleToFile (Handle theHandle, FSSpecPtr theFSSpecPtr) |
{ |
short myRefNum = 0; |
long mySize = 0; |
OSErr myErr = paramErr; |
#if TARGET_OS_MAC |
short myVolNum; |
#endif |
if (theHandle == NULL) |
goto bail; |
mySize = GetHandleSize(theHandle); |
if (mySize == 0) |
goto bail; |
HLock(theHandle); |
// delete the file; |
// if it doesn't exist yet, we'll get an error (fnfErr), which we just ignore |
myErr = FSpDelete(theFSSpecPtr); |
// create and open the file |
myErr = FSpCreate(theFSSpecPtr, kSettingsFileCreator, kSettingsFileType, smSystemScript); |
if (myErr == noErr) |
myErr = FSpOpenDF(theFSSpecPtr, fsRdWrPerm, &myRefNum); |
// position the file mark to the beginning of the file and write the data |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, 0); |
if (myErr == noErr) |
myErr = FSWrite(myRefNum, &mySize, *theHandle); |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, mySize); |
// resize the file to the number of bytes written |
if (myErr == noErr) |
myErr = SetEOF(myRefNum, mySize); |
// close the file |
if (myErr == noErr) |
myErr = FSClose(myRefNum); |
#if TARGET_OS_MAC |
// flush the volume |
if (myErr == noErr) |
myErr = GetVRefNum(myRefNum, &myVolNum); |
if (myErr == noErr) |
myErr = FlushVol(NULL, myVolNum); |
#endif |
bail: |
HUnlock(theHandle); |
return(myErr); |
} |
////////// |
// |
// QTDX_ReadHandleFromFile |
// Read the data in the specified file into a new handle. |
// |
////////// |
Handle QTDX_ReadHandleFromFile (FSSpecPtr theFSSpecPtr) |
{ |
Handle myHandle = NULL; |
short myRefNum = 0; |
long mySize = 0; |
OSErr myErr = noErr; |
// open the file |
myErr = FSpOpenDF(theFSSpecPtr, fsRdWrPerm, &myRefNum); |
if (myErr == noErr) |
myErr = SetFPos(myRefNum, fsFromStart, 0); |
// get the size of the file data |
if (myErr == noErr) |
myErr = GetEOF(myRefNum, &mySize); |
// allocate a new handle |
if (myErr == noErr) |
myHandle = NewHandleClear(mySize); |
if (myHandle == NULL) |
goto bail; |
// read the data from the file into the handle |
if (myErr == noErr) |
myErr = FSRead(myRefNum, &mySize, *myHandle); |
bail: |
if (myRefNum != 0) |
FSClose(myRefNum); |
return(myHandle); |
} |
////////// |
// |
// QTDX_EstimateRemainingTime |
// Estimate the amount of time remaining in the operation. |
// |
////////// |
void QTDX_EstimateRemainingTime (Rect *theRect, Fixed thePercentDone, UInt32 theTicksElapsed) |
{ |
char myString[32]; |
Fixed myEstTicks; |
UInt32 myRemSeconds; |
Rect myEraseRect; |
StringPtr myPString = NULL; |
myEstTicks = FixMul(FixDiv(fixed1, thePercentDone), Long2Fix(theTicksElapsed)); |
myRemSeconds = Fix2Long(FixDiv(myEstTicks - Long2Fix(theTicksElapsed), Long2Fix(60))); |
TextSize(kTimeRemainingLabelSize); |
TextFont(1); |
myPString = QTUtils_ConvertCToPascalString(kTimeRemainingLabel); |
MoveTo(theRect->left, theRect->bottom); |
DrawString(myPString); |
MacSetRect(&myEraseRect, |
theRect->left + StringWidth(myPString), |
theRect->top, |
theRect->right, |
theRect->bottom); |
free(myPString); |
EraseRect(&myEraseRect); |
MoveTo(myEraseRect.left, myEraseRect.bottom); |
// the early percentages give inaccurate estimates, so don't start displaying the |
// time until we've reached a minimum threshold |
if (thePercentDone < kMinimumUsefulPercent) |
return; |
if (myRemSeconds == 1) |
sprintf_s(myString, 32,"%u second", myRemSeconds); |
else |
sprintf_s(myString, 32,"%u seconds", myRemSeconds); |
myPString = QTUtils_ConvertCToPascalString(myString); |
DrawString(myPString); |
free(myPString); |
} |
Copyright © 2006 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2006-07-20