-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlisting12.html
executable file
·1535 lines (1226 loc) · 43.7 KB
/
listing12.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>ThreadsImporter - /QTDataRef.c</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/QuickTime/index.html">QuickTime</a> > <a href="../../samplecode/QuickTime/idxCocoa-date.html">Cocoa</a> > <A HREF="javascript:location.replace('index.html');">ThreadsImporter</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">ThreadsImporter</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/QTDataRef.c</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/AutoRunSettings.h</option>
<option value="listing2.html">/AutoRunSettings.m</option>
<option value="listing3.html">/DataRefUtilities.c</option>
<option value="listing4.html">/DataRefUtilities.h</option>
<option value="listing5.html">/FileObject.h</option>
<option value="listing6.html">/FileObject.m</option>
<option value="listing7.html">/main.m</option>
<option value="listing8.html">/MyDocument.h</option>
<option value="listing9.html">/MyDocument.m</option>
<option value="listing10.html">/MyQuickDrawView.h</option>
<option value="listing11.html">/MyQuickDrawView.m</option>
<option value="listing12.html">/QTDataRef.c</option>
<option value="listing13.html">/QTDataRef.h</option>
<option value="listing14.html">/ThreadData.h</option>
<option value="listing15.html">/URLUtilities.c</option>
<option value="listing16.html">/URLUtilities.h</option>
<option value="listing17.html">/WorkerThread.c</option>
<option value="listing18.html">/WorkerThread.h</option></select>
</p>
</form>
<p><strong><a href="ThreadsImporter.zip">Download Sample</a></strong> (“ThreadsImporter.zip”, 218.2K)<BR>
<strong><a href="ThreadsImporter.dmg">Download Sample</a></strong> (“ThreadsImporter.dmg”, 282.3K)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox">/* File: QTDataRef.c Description: Document-specific code for thread-safety test application. Author: QTEngineering, dts Copyright: © Copyright 2003-2004 Apple Computer, Inc. All rights reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Change History (most recent first): <1> dts 11/16/03 initial release*/////////////// header files////////////#include "QTDataRef.h"////////////// global variables////////////extern short gAppResFile; // file reference number for this application's resource fileextern ModalFilterUPP gModalFilterUPP; // UPP to our custom dialog event filterPtr gDataBuffer = NULL; // buffer that holds data being transferredComponentInstance gDataReader = NULL; // the data handler that reads data from the URLComponentInstance gDataWriter = NULL; // the data handler that writes data to a fileDataHCompletionUPP gReadDataHCompletionUPP = NULL;DataHCompletionUPP gWriteDataHCompletionUPP = NULL;long gBytesToTransfer = 0L; // the number of bytes to transferlong gBytesTransferred = 0L; // the number of bytes already transferredBoolean gDoneTransferring = false; // are we done transferring data?#if TARGET_OS_WIN32UINT gTimerID; // ID of the timer that tasks the data handlers#endif/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Data reference creation utilities.//// Use these functions to create data references./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_MakeFileDataRef// Return a file data reference for the specified file.//// The caller is responsible for disposing of the handle returned by this function (by calling DisposeHandle).////////////Handle QTDR_MakeFileDataRef (FSSpecPtr theFile){ Handle myDataRef = NULL; QTNewAlias(theFile, (AliasHandle *)&myDataRef, true); return(myDataRef);}////////////// QTDR_MakeResourceDataRef// Return a resource data reference for the specified file.//// The caller is responsible for disposing of the handle returned by this function (by calling DisposeHandle).////////////Handle QTDR_MakeResourceDataRef (FSSpecPtr theFile, OSType theResType, SInt16 theResID){ Handle myDataRef = NULL; OSType myResType; SInt16 myResID; OSErr myErr = noErr; myDataRef = QTDR_MakeFileDataRef(theFile); if (myDataRef == NULL) goto bail; // append the resource type and ID to the data reference myResType = EndianU32_NtoB(theResType); myResID = EndianS16_NtoB(theResID); myErr = PtrAndHand(&myResType, myDataRef, sizeof(myResType)); if (myErr == noErr) myErr = PtrAndHand(&myResID, myDataRef, sizeof(myResID));bail: if (myErr != noErr) { if (myDataRef != NULL) DisposeHandle(myDataRef); myDataRef = NULL; } return(myDataRef);}////////////// QTDR_MakeHandleDataRef// Return a handle data reference for the specified handle.//// The caller is responsible for disposing of the handle returned by this function (by calling DisposeHandle).////////////Handle QTDR_MakeHandleDataRef (Handle theHandle){ Handle myDataRef = NULL; myDataRef = NewHandleClear(sizeof(Handle)); if (myDataRef != NULL) BlockMove(&theHandle, *myDataRef, sizeof(Handle)); // the following single line can replace the preceding three lines// PtrToHand(&theHandle, &myDataRef, sizeof(Handle)); return(myDataRef);}////////////// QTDR_MakeURLDataRef// Return a URL data reference for the specified URL.//// The caller is responsible for disposing of the handle returned by this function (by calling DisposeHandle).////////////Handle QTDR_MakeURLDataRef (char *theURL){ Handle myDataRef = NULL; Size mySize = 0; // get the size of the URL, plus the terminating null byte mySize = (Size)strlen(theURL) + 1; if (mySize == 1) goto bail; // allocate a new handle and copy the URL into the handle myDataRef = NewHandleClear(mySize); if (myDataRef != NULL) BlockMove(theURL, *myDataRef, mySize);bail: return(myDataRef);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Movie-retrieval utilities.//// Use these functions to get movies specified using data references./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_GetMovieFromFile// Get the movie stored in the specified file.////////////Movie QTDR_GetMovieFromFile (FSSpecPtr theFile){ Movie myMovie = NULL; Handle myDataRef = NULL; myDataRef = QTDR_MakeFileDataRef(theFile); if (myDataRef != NULL) { NewMovieFromDataRef(&myMovie, newMovieActive, NULL, myDataRef, rAliasType); DisposeHandle(myDataRef); } return(myMovie);}////////////// QTDR_GetMovieFromHandle// Get the movie stored in the specified block of memory.////////////Movie QTDR_GetMovieFromHandle (Handle theHandle){ Movie myMovie = NULL; Handle myDataRef = NULL; myDataRef = QTDR_MakeHandleDataRef(theHandle); if (myDataRef != NULL) { NewMovieFromDataRef(&myMovie, newMovieActive, NULL, myDataRef, HandleDataHandlerSubType); DisposeHandle(myDataRef); } return(myMovie);}////////////// QTDR_GetMovieFromResource// Get the movie stored in the specified resource.////////////Movie QTDR_GetMovieFromResource (FSSpecPtr theFile, OSType theResType, SInt16 theResID){ Movie myMovie = NULL; Handle myDataRef = NULL; myDataRef = QTDR_MakeResourceDataRef(theFile, theResType, theResID); if (myDataRef != NULL) { NewMovieFromDataRef(&myMovie, newMovieActive, NULL, myDataRef, ResourceDataHandlerSubType); DisposeHandle(myDataRef); } return(myMovie);}////////////// QTDR_GetMovieFromURL// Get the movie in the file referenced by the specified uniform resource locator (URL).////////////Movie QTDR_GetMovieFromURL (char *theURL){ Movie myMovie = NULL; Handle myDataRef = NULL; myDataRef = QTDR_MakeURLDataRef(theURL); if (myDataRef != NULL) { NewMovieFromDataRef(&myMovie, newMovieActive, NULL, myDataRef, URLDataHandlerSubType); DisposeHandle(myDataRef); } return(myMovie);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// URL utilities.//// Use these functions to elicit URLs from the user and get the basename of a URL./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_GetURLFromUser// Display a dialog box to elicit a URL from the user; return a C string that contains the text in the// dialog box when the user clicks the OK button; otherwise, return NULL.//// The caller is responsible for disposing of the pointer returned by this function (by calling free).//// Note that the URLs handled here are limited to 255 characters; supporting longer URLs is left as an// exercise for the reader.////////////char *QTDR_GetURLFromUser (short thePromptStringIndex){ short myItem; short mySavedResFile; GrafPtr mySavedPort; DialogPtr myDialog = NULL; short myItemKind; Handle myItemHandle; Rect myItemRect; Str255 myString; char *myURL = NULL; OSErr myErr = noErr; ////////// // // save the current resource file and graphics port // ////////// mySavedResFile = CurResFile(); GetPort(&mySavedPort); // set the application's resource file UseResFile(gAppResFile); ////////// // // create the dialog box in which the user will enter a URL // ////////// myDialog = GetNewDialog(kGetURL_DLOGID, NULL, (WindowPtr)-1L); if (myDialog == NULL) goto bail; QTFrame_ActivateController(QTFrame_GetFrontMovieWindow(), false); MacSetPort(GetDialogPort(myDialog)); SetDialogDefaultItem(myDialog, kGetURL_OKButton); SetDialogCancelItem(myDialog, kGetURL_CancelButton); // set the prompt string GetIndString(myString, kTextKindsResourceID, thePromptStringIndex); GetDialogItem(myDialog, kGetURL_URLLabelItem, &myItemKind, &myItemHandle, &myItemRect); SetDialogItemText(myItemHandle, myString); MacShowWindow(GetDialogWindow(myDialog)); ////////// // // display and handle events in the dialog box until the user clicks OK or Cancel // ////////// do { ModalDialog(gModalFilterUPP, &myItem); } while ((myItem != kGetURL_OKButton) && (myItem != kGetURL_CancelButton)); ////////// // // handle the selected button // ////////// if (myItem != kGetURL_OKButton) { myErr = userCanceledErr; goto bail; } // retrieve the edited text GetDialogItem(myDialog, kGetURL_URLTextItem, &myItemKind, &myItemHandle, &myItemRect); GetDialogItemText(myItemHandle, myString); myURL = QTUtils_ConvertPascalToCString(myString); bail: // restore the previous resource file and graphics port MacSetPort(mySavedPort); UseResFile(mySavedResFile); if (myDialog != NULL) DisposeDialog(myDialog); return(myURL);}////////////// QTDR_GetURLBasename// Return the basename of the specified URL.//// The basename of a URL is the portion of the URL following the rightmost URL separator. This function// is useful for setting window titles of movies opened using the URL data handler to the basename of a// URL (just like QuickTime Player does).//// The caller is responsible for disposing of the pointer returned by this function (by calling free).////////////char *QTDR_GetURLBasename (char *theURL){ char *myBasename = NULL; short myLength = 0; short myIndex; // make sure we got a URL passed in if (theURL == NULL) goto bail; // get the length of the URL myLength = strlen(theURL); // find the position of the rightmost URL separator in theURL if (strchr(theURL, kURLSeparator) != NULL) { myIndex = myLength - 1; while (theURL[myIndex] != kURLSeparator) myIndex--; // calculate the length of the basename myLength = myLength - myIndex - 1; } else { // there is no rightmost URL separator in theURL; // set myIndex so that myIndex + 1 == 0, for the call to BlockMove below myIndex = -1; } // allocate space to hold the string that we return to the caller myBasename = malloc(myLength + 1); if (myBasename == NULL) goto bail; // copy into myBasename the substring of theURL from myIndex + 1 to the end BlockMove(&theURL[myIndex + 1], myBasename, myLength); myBasename[myLength] = '\0'; bail: return(myBasename);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Data reference extension functions.//// Use these functions to add extensions to data references./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_AddFilenamingExtension// Add a filenaming extension to a data reference. If theStringPtr is NULL, add a 0-length filename.//// A filenaming extension is a Pascal string.////////////OSErr QTDR_AddFilenamingExtension (Handle theDataRef, StringPtr theFileName){ unsigned char myChar = 0; OSErr myErr = noErr; if (theFileName == NULL) myErr = PtrAndHand(&myChar, theDataRef, sizeof(myChar)); else myErr = PtrAndHand(theFileName, theDataRef, theFileName[0] + 1); return(myErr);}////////////// QTDR_AddMacOSFileTypeDataRefExtension// Add a Macintosh file type as a data reference extension.//// A Macintosh file type data extension is an atom whose data is a 4-byte OSType.////////////OSErr QTDR_AddMacOSFileTypeDataRefExtension (Handle theDataRef, OSType theType){ unsigned long myAtomHeader[2]; OSType myType; OSErr myErr = noErr; myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader) + sizeof(theType)); myAtomHeader[1] = EndianU32_NtoB(kDataRefExtensionMacOSFileType); myType = EndianU32_NtoB(theType); myErr = PtrAndHand(myAtomHeader, theDataRef, sizeof(myAtomHeader)); if (myErr == noErr) myErr = PtrAndHand(&myType, theDataRef, sizeof(myType)); return(myErr);}////////////// QTDR_AddMIMETypeDataRefExtension// Add a MIME type as a data reference extension.//// A MIME type data extension is an atom whose data is a Pascal string.////////////OSErr QTDR_AddMIMETypeDataRefExtension (Handle theDataRef, StringPtr theMIMEType){ unsigned long myAtomHeader[2]; OSErr myErr = noErr; if (theMIMEType == NULL) return(paramErr); myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader) + theMIMEType[0] + 1); myAtomHeader[1] = EndianU32_NtoB(kDataRefExtensionMIMEType); myErr = PtrAndHand(myAtomHeader, theDataRef, sizeof(myAtomHeader)); if (myErr == noErr) myErr = PtrAndHand(theMIMEType, theDataRef, theMIMEType[0] + 1); return(myErr);}////////////// QTDR_AddInitDataDataRefExtension// Add some initialization data as a data reference extension.//// An initialization data data extension is an atom whose data is any block of data.////////////OSErr QTDR_AddInitDataDataRefExtension (Handle theDataRef, Ptr theInitDataPtr){ unsigned long myAtomHeader[2]; OSErr myErr = noErr; if (theInitDataPtr == NULL) return(paramErr); myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader) + GetPtrSize(theInitDataPtr)); myAtomHeader[1] = EndianU32_NtoB(kDataRefExtensionInitializationData); myErr = PtrAndHand(myAtomHeader, theDataRef, sizeof(myAtomHeader)); if (myErr == noErr) myErr = PtrAndHand(theInitDataPtr, theDataRef, GetPtrSize(theInitDataPtr)); return(myErr);}/////////////////////////////////////////////////////////////////////////////////////////////////////////////// File-transfer functions.//// These functions implement our file-transfer capability./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_CopyRemoteFileToLocalFile// Copy a remote file (located at the specified URL) into a local file.////////////OSErr QTDR_CopyRemoteFileToLocalFile (char *theURL, FSSpecPtr theFile){ Handle myReaderRef = NULL; // data reference for the remote file Handle myWriterRef = NULL; // data reference for the local file ComponentResult myErr = badComponentType; ////////// // // create the local file with the desired type and creator // ////////// // delete the target local file, if it already exists; // if it doesn't exist yet, we'll get an error (fnfErr), which we just ignore FSpDelete(theFile); myErr = FSpCreate(theFile, kTransFileCreator, kTransFileType, smSystemScript); if (myErr != noErr) goto bail; ////////// // // create data references for the remote file and the local file // ////////// myReaderRef = QTDR_MakeURLDataRef(theURL); if (myReaderRef == NULL) goto bail; myWriterRef = QTDR_MakeFileDataRef(theFile); if (myWriterRef == NULL) goto bail; ////////// // // find and open the URL and file data handlers; connect the data references to them // ////////// gDataReader = OpenComponent(GetDataHandler(myReaderRef, URLDataHandlerSubType, kDataHCanRead)); if (gDataReader == NULL) goto bail; gDataWriter = OpenComponent(GetDataHandler(myWriterRef, rAliasType, kDataHCanWrite)); if (gDataWriter == NULL) goto bail; // set the data reference for the URL data handler myErr = DataHSetDataRef(gDataReader, myReaderRef); if (myErr != noErr) goto bail; // set the data reference for the file data handler myErr = DataHSetDataRef(gDataWriter, myWriterRef); if (myErr != noErr) goto bail; ////////// // // allocate a data buffer; the URL data handler copies data into this buffer, // and the file data handler copies data out of it // ////////// gDataBuffer = NewPtrClear(kDataBufferSize); myErr = MemError(); if (myErr != noErr) goto bail; ////////// // // connect to the remote and local files // ////////// // open a read-only path to the remote data reference myErr = DataHOpenForRead(gDataReader); if (myErr != noErr) goto bail; // get the size of the remote file myErr = DataHGetFileSize(gDataReader, &gBytesToTransfer); if (myErr != noErr) goto bail; // open a write-only path to the local data reference myErr = DataHOpenForWrite(gDataWriter); if (myErr != noErr) goto bail; ////////// // // start reading and writing data // ////////// gDoneTransferring = false; gBytesTransferred = 0L; gReadDataHCompletionUPP = NewDataHCompletionUPP(QTDR_ReadDataCompletionProc); gWriteDataHCompletionUPP = NewDataHCompletionUPP(QTDR_WriteDataCompletionProc); // start retrieving the data; we do this by calling our own write completion routine, // pretending that we've just successfully finished writing 0 bytes of data QTDR_WriteDataCompletionProc(gDataBuffer, 0L, noErr);bail: // if we encountered any error, close the data handler components if (myErr != noErr) QTDR_CloseDownHandlers(); return((OSErr)myErr);}////////////// QTDR_ReadDataCompletionProc// This procedure is called when the data handler has completed a read operation.//// The theRefCon parameter contains the number of bytes just read.////////////PASCAL_RTN void QTDR_ReadDataCompletionProc (Ptr theRequest, long theRefCon, OSErr theErr){#pragma unused(theErr) // we just finished reading some data, so schedule a write operation DataHWrite( gDataWriter, theRequest, // the data buffer gBytesTransferred, // write from the current offset theRefCon, // the number of bytes to write gWriteDataHCompletionUPP, theRefCon);}////////////// QTDR_WriteDataCompletionProc// This procedure is called when the data handler has completed a write operation.//// The theRefCon parameter contains the number of bytes just written.////////////PASCAL_RTN void QTDR_WriteDataCompletionProc (Ptr theRequest, long theRefCon, OSErr theErr){#pragma unused(theErr) long myNumBytesToRead; wide myWide; // increment our tally of the number of bytes written so far gBytesTransferred += theRefCon; if (gBytesTransferred < gBytesToTransfer) { // there is still data to read and write, so schedule a read operation // determine how big a chunk to read if (gBytesToTransfer - gBytesTransferred > kDataBufferSize) myNumBytesToRead = kDataBufferSize; else myNumBytesToRead = gBytesToTransfer - gBytesTransferred; myWide.lo = gBytesTransferred; // read from the current offset myWide.hi = 0; // schedule a read operation DataHReadAsync(gDataReader, theRequest, // the data buffer myNumBytesToRead, &myWide, gReadDataHCompletionUPP, myNumBytesToRead); } else { // we've transferred all the data, so set a flag to tell us to close down the data handlers gDoneTransferring = true; } }////////////// QTDR_CloseDownHandlers// Close our read/write access to our data references and then close down the read/write data handlers.////////////void QTDR_CloseDownHandlers (void){ if (gDataReader != NULL) { DataHCloseForRead(gDataReader); CloseComponent(gDataReader); gDataReader = NULL; } if (gDataWriter != NULL) { DataHCloseForWrite(gDataWriter); CloseComponent(gDataWriter); gDataWriter = NULL; } // dispose of the data buffer if (gDataBuffer != NULL) DisposePtr(gDataBuffer); // dispose of the routine descriptors if (gReadDataHCompletionUPP != NULL) DisposeDataHCompletionUPP(gReadDataHCompletionUPP); if (gWriteDataHCompletionUPP != NULL) DisposeDataHCompletionUPP(gWriteDataHCompletionUPP); gDoneTransferring = false; #if TARGET_OS_WIN32 // kill the timer that tasks the data handlers KillTimer(NULL, gTimerID);#endif}////////////// QTDR_TimerProc// Handle timer messages to task the data handlers.////////////#if TARGET_OS_WIN32void CALLBACK QTDR_TimerProc (HWND theWnd, UINT theMessage, UINT theID, DWORD theTime){#pragma unused(theWnd, theMessage, theID, theTime) QTApp_HandleEvent(NULL);}#endif/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Other functions.//// These functions are called by ComApplication.c./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_CreateReferenceCopy// Create a copy of the given file that is a reference movie (that is, a movie file and a separate// media file).////////////OSErr QTDR_CreateReferenceCopy (Movie theSrcMovie, FSSpecPtr theDstMovieFile, FSSpecPtr theDstMediaFile){ Track mySrcTrack = NULL; Media mySrcMedia = NULL; Movie myDstMovie = NULL; Track myDstTrack = NULL; Media myDstMedia = NULL; Handle myMediaRef = NULL; // data reference for the media file#if !USE_ADDEMPTYTRACKTOMOVIE Fixed myWidth, myHeight; OSType myType;#endif long myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile; short myResRefNum = 0; short myResID = movieInDataForkResID; OSErr myErr = paramErr; // get the first video track and media in the source movie mySrcTrack = GetMovieIndTrackType(theSrcMovie, 1, VideoMediaType, movieTrackMediaType); if (mySrcTrack == NULL) goto bail; mySrcMedia = GetTrackMedia(mySrcTrack); if (mySrcMedia == NULL) goto bail; // create a file data reference for the new media file myMediaRef = QTDR_MakeFileDataRef(theDstMediaFile); if (myMediaRef == NULL) goto bail; // create a file for the destination movie data myErr = FSpCreate(theDstMediaFile, sigMoviePlayer, MovieFileType, 0); if (myErr != noErr) goto bail; // create a file for the destination movie atom and create an empty movie myErr = CreateMovieFile(theDstMovieFile, sigMoviePlayer, smCurrentScript, myFlags, &myResRefNum, &myDstMovie); if (myErr != noErr) goto bail; // assign the default progress proc to the destination movie SetMovieProgressProc(myDstMovie, (MovieProgressUPP)-1, 0);#if USE_ADDEMPTYTRACKTOMOVIE myErr = AddEmptyTrackToMovie(mySrcTrack, myDstMovie, myMediaRef, rAliasType, &myDstTrack); if (myErr != noErr) goto bail; myDstMedia = GetTrackMedia(myDstTrack); myErr = GetMoviesError(); if (myErr != noErr) goto bail;#else // get some information about the source track and media GetTrackDimensions(mySrcTrack, &myWidth, &myHeight); GetMediaHandlerDescription(mySrcMedia, &myType, 0, 0); // create the destination movie track and media myDstTrack = NewMovieTrack(myDstMovie, myWidth, myHeight, kNoVolume); myErr = GetMoviesError(); if (myErr != noErr) goto bail; myDstMedia = NewTrackMedia(myDstTrack, myType, GetMediaTimeScale(mySrcMedia), myMediaRef, rAliasType); myErr = GetMoviesError(); if (myErr != noErr) goto bail; CopyTrackSettings(mySrcTrack, myDstTrack);#endif // copy the entire source track into the destination track; this copies the track's media // samples into the destination media file myErr = BeginMediaEdits(myDstMedia); if (myErr != noErr) goto bail; myErr = InsertTrackSegment(mySrcTrack, myDstTrack, 0, GetTrackDuration(mySrcTrack), 0); if (myErr != noErr) goto bail; myErr = EndMediaEdits(myDstMedia); if (myErr != noErr) goto bail; // add the movie atom to the data fork of the movie file myErr = AddMovieResource(myDstMovie, myResRefNum, &myResID, NULL);bail: return(myErr);}////////////// QTDR_PlayMovieFromRAM// Play a movie.////////////OSErr QTDR_PlayMovieFromRAM (Movie theMovie){ WindowPtr myWindow = NULL; Rect myBounds = {50, 50, 100, 100}; Rect myRect; StringPtr myTitle = QTUtils_ConvertCToPascalString(kWindowTitle); OSErr myErr = memFullErr; myWindow = NewCWindow(NULL, &myBounds, myTitle, false, 0, (WindowPtr)-1, false, 0); if (myWindow == NULL) goto bail; myErr = noErr; MacSetPort((GrafPtr)GetWindowPort(myWindow)); GetMovieBox(theMovie, &myRect); MacOffsetRect(&myRect, -myRect.left, -myRect.top); SetMovieBox(theMovie, &myRect); if (!EmptyRect(&myRect)) SizeWindow(myWindow, myRect.right, myRect.bottom, false); else SizeWindow(myWindow, 200, 0, false); MacShowWindow(myWindow); SetMovieGWorld(theMovie, GetWindowPort(myWindow), NULL); GoToBeginningOfMovie(theMovie); MoviesTask(theMovie, 0); StartMovie(theMovie); myErr = GetMoviesError(); if (myErr != noErr) goto bail; while (!IsMovieDone(theMovie)) MoviesTask(theMovie, 0);bail: free(myTitle); if (theMovie != NULL) DisposeMovie(theMovie); if (myWindow != NULL) DisposeWindow(myWindow); return(myErr);}////////////// QTDR_CreateMovieInRAM// Create a movie in RAM.////////////OSErr QTDR_CreateMovieInRAM (void){ Movie myMovie = NULL; Track myTrack = NULL; Media myMedia = NULL; short myResRefNum = 0; short myResID = 0; Handle myDataRef = NULL; Handle myHandle = NULL; FSSpec myFSSpec; OSErr myErr = noErr; // create a new handle to hold the media data myHandle = NewHandleClear(0); if (myHandle == NULL) goto bail; // create a data reference to that handle myDataRef = QTDR_MakeHandleDataRef(myHandle); if (myDataRef == NULL) goto bail; myMovie = NewMovie(newMovieActive); if (myMovie == NULL) goto bail; myErr = SetMovieDefaultDataRef(myMovie, myDataRef, HandleDataHandlerSubType); if (myErr != noErr) goto bail; // create the movie track and media myTrack = NewMovieTrack(myMovie, FixRatio(kVideoTrackWidth, 1), FixRatio(kVideoTrackHeight, 1), kNoVolume); myErr = GetMoviesError(); if (myErr != noErr) goto bail; myMedia = NewTrackMedia(myTrack, VideoMediaType, kVideoTimeScale, NULL, 0); myErr = GetMoviesError(); if (myErr != noErr) goto bail; // create the media samples myErr = BeginMediaEdits(myMedia); if (myErr != noErr) goto bail; myErr = QTDR_AddVideoSamplesToMedia(myMedia, kVideoTrackWidth, kVideoTrackHeight); if (myErr != noErr) goto bail; myErr = EndMediaEdits(myMedia); if (myErr != noErr) goto bail; // add the media to the track myErr = InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1); if (myErr != noErr) goto bail; // add the movie atom to the movie file myErr = AddMovieResource(myMovie, myResRefNum, &myResID, NULL); myFSSpec.name[0] = (unsigned char)0; myFSSpec.parID = 0; myFSSpec.vRefNum = 0; QTFrame_OpenMovieInWindow(myMovie, &myFSSpec);bail: if (myDataRef != NULL) DisposeHandle(myDataRef); return(myErr);}////////////// QTDR_CreateTrackInRAM// Create a track in RAM, with the media data stored in an initialization data data reference extension.////////////OSErr QTDR_CreateTrackInRAM (Movie theMovie){ Track myTrack = NULL; Media myMedia = NULL; Handle myDataRef = NULL; unsigned long myAtomHeader[2]; OSErr myErr = noErr; if (theMovie == NULL) return(paramErr); myDataRef = NewHandleClear(sizeof(Handle) + sizeof(char)); if (myDataRef == NULL) return(MemError()); myAtomHeader[0] = EndianU32_NtoB(sizeof(myAtomHeader)); myAtomHeader[1] = EndianU32_NtoB(kDataRefExtensionInitializationData); myErr = PtrAndHand(myAtomHeader, myDataRef, sizeof(myAtomHeader)); if (myErr != noErr) goto bail; // create the movie track and media myTrack = NewMovieTrack(theMovie, FixRatio(kVideoTrackWidth, 1), FixRatio(kVideoTrackHeight, 1), kNoVolume); myErr = GetMoviesError(); if (myErr != noErr) goto bail; myMedia = NewTrackMedia(myTrack, VideoMediaType, kVideoTimeScale, myDataRef, HandleDataHandlerSubType); myErr = GetMoviesError(); if (myErr != noErr) goto bail; // create the media samples myErr = BeginMediaEdits(myMedia); if (myErr != noErr) goto bail; myErr = QTDR_AddVideoSamplesToMedia(myMedia, kVideoTrackWidth, kVideoTrackHeight); if (myErr != noErr) goto bail; myErr = EndMediaEdits(myMedia); if (myErr != noErr) goto bail; // add the media to the track myErr = InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1); bail: if (myDataRef != NULL) DisposeHandle(myDataRef); return(myErr);}////////////// QTDR_AddVideoSamplesToMedia// Add video media samples to the specified media.////////////static OSErr QTDR_AddVideoSamplesToMedia (Media theMedia, short theTrackWidth, short theTrackHeight){ GWorldPtr myGWorld = NULL; PixMapHandle myPixMap = NULL; CodecType myCodecType = kJPEGCodecType; long myNumSample; long myMaxComprSize = 0L; Handle myComprDataHdl = NULL; Ptr myComprDataPtr = NULL; ImageDescriptionHandle myImageDesc = NULL; CGrafPtr mySavedPort = NULL; GDHandle mySavedDevice = NULL; Rect myRect; OSErr myErr = noErr; MacSetRect(&myRect, 0, 0, theTrackWidth, theTrackHeight); myErr = NewGWorld(&myGWorld, kPixelDepth, &myRect, NULL, NULL, (GWorldFlags)0); if (myErr != noErr) goto bail; myPixMap = GetGWorldPixMap(myGWorld); if (myPixMap == NULL) goto bail; LockPixels(myPixMap); myErr = GetMaxCompressionSize( myPixMap, &myRect, 0, // let ICM choose depth codecNormalQuality, myCodecType, (CompressorComponent)anyCodec, &myMaxComprSize); if (myErr != noErr) goto bail; myComprDataHdl = NewHandle(myMaxComprSize); if (myComprDataHdl == NULL) goto bail; HLockHi(myComprDataHdl);#if TARGET_CPU_68K myComprDataPtr = StripAddress(*myComprDataHdl);#else myComprDataPtr = *myComprDataHdl;#endif myImageDesc = (ImageDescriptionHandle)NewHandle(4); if (myImageDesc == NULL) goto bail; GetGWorld(&mySavedPort, &mySavedDevice); SetGWorld(myGWorld, NULL); for (myNumSample = 1; myNumSample <= kNumVideoFrames; myNumSample++) { EraseRect(&myRect); QTDR_DrawFrame(theTrackWidth, theTrackHeight, myNumSample, myGWorld); myErr = CompressImage( myPixMap, &myRect, codecNormalQuality, myCodecType, myImageDesc, myComprDataPtr); if (myErr != noErr) goto bail; myErr = AddMediaSample( theMedia, myComprDataHdl, 0, // no offset in data (**myImageDesc).dataSize, kVideoFrameDuration, // frame duration (SampleDescriptionHandle)myImageDesc, 1, // one sample 0, // self-contained samples NULL); if (myErr != noErr) goto bail; }bail: SetGWorld(mySavedPort, mySavedDevice); if (myImageDesc != NULL) DisposeHandle((Handle)myImageDesc); if (myComprDataHdl != NULL) DisposeHandle(myComprDataHdl); if (myGWorld != NULL) DisposeGWorld(myGWorld); return(myErr);}////////////// QTDR_DrawFrame// Draw a frame of video.////////////static void QTDR_DrawFrame (short theTrackWidth, short theTrackHeight, long theNumSample, GWorldPtr theGWorld){ Handle myHandle = NULL; char myData[kPICTFileHeaderSize]; static PicHandle myPicture = NULL; static GWorldPtr myGWorld = NULL; static GraphicsImportComponent myImporter = NULL; Rect myRect; RGBColor myColor; ComponentResult myErr = noErr; MacSetRect(&myRect, 0, 0, theTrackWidth, theTrackHeight); if (myPicture == NULL) { myErr = NewGWorld(&myGWorld, kPixelDepth, &myRect, NULL, NULL, (GWorldFlags)0); if (myErr != noErr) goto bail; // read a picture from our resource file myPicture = GetPicture(kPictureID); if (myPicture == NULL) goto bail; // use Munger to prepend a 512-byte header onto the picture data; this converts the PICT // resource data into in-memory PICT file data (see Ice Floe 14 for an explanation of this) myHandle = (Handle)myPicture; Munger(myHandle, 0, NULL, 0, myData, kPICTFileHeaderSize); // get a graphics importer for the picture myErr = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &myImporter); if (myErr != noErr) goto bail; // configure the graphics importer myErr = GraphicsImportSetGWorld(myImporter, myGWorld, NULL); if (myErr != noErr) goto bail; myErr = GraphicsImportSetDataHandle(myImporter, myHandle); if (myErr != noErr) goto bail; myErr = GraphicsImportSetBoundsRect(myImporter, &myRect); if (myErr != noErr) goto bail; // draw the picture into the source GWorld myErr = GraphicsImportDraw(myImporter); if (myErr != noErr) goto bail; } // set the blend amount (0 = fully transparent; 0xffff = fully opaque) myColor.red = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); myColor.green = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); myColor.blue = (theNumSample - 1) * (0xffff / kNumVideoFrames - 1); OpColor(&myColor); // blend the picture (in the source GWorld) into the empty rectangle (in the destination GWorld) CopyBits((BitMapPtr)*GetGWorldPixMap(myGWorld), (BitMapPtr)*GetGWorldPixMap(theGWorld), &myRect, &myRect, blend, NULL); if (theNumSample == kNumVideoFrames) goto bail; return; bail: if (myHandle != NULL) DisposeHandle(myHandle); if (myPicture != NULL) ReleaseResource((Handle)myPicture); if (myImporter != NULL) CloseComponent(myImporter);} /////////////////////////////////////////////////////////////////////////////////////////////////////////////// Utility functions./////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QTDR_IsMovieSelfContained// Is the specified movie a self-contained movie?////////////Boolean QTDR_IsMovieSelfContained (Movie theMovie){ long myTrackCount = 0L; long myTrackIndex = 0L; short myMediaRefCount = 0L; short myMediaRefIndex = 0L; Media myMedia = NULL; long myAttrs = 0L; OSErr myErr = noErr; myTrackCount = GetMovieTrackCount(theMovie); for (myTrackIndex = 1; myTrackIndex <= myTrackCount; myTrackIndex++) { myMedia = GetTrackMedia(GetMovieIndTrack(theMovie, myTrackIndex)); if (myMedia != NULL) { myErr = GetMediaDataRefCount(myMedia, &myMediaRefCount); if (myErr == noErr) { for (myMediaRefIndex = 1; myMediaRefIndex <= myMediaRefCount; myMediaRefIndex++) { myErr = GetMediaDataRef(myMedia, myMediaRefIndex, NULL, NULL, &myAttrs); if (myErr == noErr) { if (!(myAttrs & dataRefSelfReference)) return(false); } } } } } return(true);}</pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/ThreadsImporter/listing12.html%3Fid%3DDTS10003146-1.0&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/ThreadsImporter/listing12.html%3Fid%3DDTS10003146-1.0&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/ThreadsImporter/listing12.html%3Fid%3DDTS10003146-1.0&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>