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.
QTShortcut.c
////////// |
// |
// File: QTShortcut.c |
// |
// Contains: Sample code for creating a shortcut to a QuickTime movie. |
// |
// Written by: Tim Monroe |
// Based on the Windows version of MakeRefMovie.c and the code in the Ice Floe Dispatch 15; |
// some comments based on release notes by Chris Flick. |
// |
// Copyright: © 1998 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <1> 11/20/98 rtm first file |
// |
// A shortcut is a QuickTime reference movie that references a single other movie. A typical reference |
// movie references more than one other movie, and the target of the reference movie is determined at |
// runtime depending on certain features of the user's machine, such as the actual components that are |
// available on the machine or the speed of the user's connection to the internet. (Reference movies |
// that select a target depending on the speed of the internet connection are "multiple data rate movies".) |
// A shortcut is essentially the simplest possible reference movie; all it does is refer to some target, |
// which is opened (or imported) when the reference movie is opened (or imported). |
// |
// Shortcut movies can be useful as a cross-platform, media-centric aliasing mechanism. The data |
// reference contained in a shortcut can be any one of the data reference types supported by QuickTime |
// (an alias to a file, a URL to an ftp or http movie, and so forth) and that reference can address any |
// kind of data that can be opened by QuickTime. Thus, you could put shortcut movies on a server that |
// point to files elsewhere on the server, on another server, or even on the user's local machine. When |
// a user opens a shortcut movie, its target data is automatically opened. This indirection allows a |
// server administrator to move the files targetted by some shortcut movies to new locations and then |
// update the shortcuts. Any client references to the shortcuts (HTML embeddings, explicit URLs used by |
// an application, and so forth) would be unaffected by this move. |
// |
// Shortcut movies have been supported by QuickTime beginning with version 3.0. QuickTime version 4.0 |
// introduced the Movie Toolbox function CreateShortcutMovieFile, which you can use to create a shortcut |
// movie given a data reference, its type, and a specification of the output shortcut movie file. This |
// sample code illustrates how to call the CreateShortcutMovieFile function. |
// |
// If you want to create shortcut movies under versions of QuickTime prior to 4.0, then you'll need to |
// build a file containing the reference data yourself. The format of reference movies is currently |
// undocumented, but it's quite simple: the shortcut file should consist entirely of a single movie atom, |
// which in turn contains a movie data reference alias atom (of type MovieDataRefAliasAID). This atom |
// contains a single data reference atom. Finally, the data reference atom should contain the type of the |
// data reference followed immediately by the data reference itself. In short: |
// |
// movie atom -> movie data reference alias atom -> data reference atom |
// |
// (where "->" means: "contains exactly one"). This sample code also shows how to assemble a shortcut |
// movie yourself by building these atoms. |
// |
// IMPORTANT: The atoms that we'll create here (for instance, reference movie descriptor atoms) |
// are unrelated to QTAtom and QTAtomContainer structures introduced in QuickTime 2.1. The atoms |
// we need to work with here are more akin to "chunks" as used in AIFF files: an atom is simply |
// a 4-byte atom length, a 4-byte atom type, and some associated data (which itself may be other |
// atoms). All this stuff (length, type, and data) must be in big-endian format. |
// |
////////// |
#include "QTShortCut.h" |
////////// |
// |
// QTShortCut_CreateShortcutMovieFile |
// Create a movie file that is a shortcut to the specified data reference. |
// |
////////// |
OSErr QTShortCut_CreateShortcutMovieFile (Handle theDataRef, OSType theDataRefType, FSSpecPtr theFSSpecPtr) |
{ |
long myVersion = 0L; |
OSErr myErr = noErr; |
myErr = Gestalt(gestaltQuickTime, &myVersion); |
if (myErr != noErr) |
goto bail; |
if (((myVersion >> 16) & 0xffff) >= 0x0400) { |
// we're running under QuickTime 4.0 or greater; we can use the function CreateShortcutMovieFile |
myErr = CreateShortcutMovieFile(theFSSpecPtr, |
kShortcutFileCreator, |
smCurrentScript, |
createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, |
theDataRef, |
theDataRefType); |
} else { |
// we're running under a version of QuickTime prior to 4.0; do the grunt work ourselves |
OSType myDataRefType; |
unsigned long myAtomHeaderSize; |
Ptr myData = NULL; |
Handle myMoovAtom = NULL; |
////////// |
// |
// create the atom data that goes into a data reference atom (we will create this atom's |
// header when we create the movie atom that contains it); the atom data is the data reference |
// type followed by the data reference itself |
// |
////////// |
myDataRefType = EndianU32_NtoB(theDataRefType); |
myAtomHeaderSize = 2 * sizeof(long); |
// allocate a data block and copy the data reference type and data reference into it |
myData = NewPtrClear(sizeof(OSType) + GetHandleSize(theDataRef)); |
if (myData == NULL) |
goto bail; |
BlockMove(&myDataRefType, myData, sizeof(OSType)); |
BlockMove(*theDataRef, (Ptr)(myData + sizeof(OSType)), GetHandleSize(theDataRef)); |
////////// |
// |
// create a handle to contain the size and type fields of the movie atom, as well as |
// the size and type fields of the movie data reference alias atom contained in it |
// and of the data reference atom contained in the movie data reference alias atom |
// |
////////// |
myMoovAtom = NewHandleClear(3 * myAtomHeaderSize); |
if (myMoovAtom == NULL) |
goto bail; |
// fill in the size and type fields of the three atoms |
*((long *)(*myMoovAtom + 0x00)) = EndianU32_NtoB((3 * myAtomHeaderSize) + GetPtrSize(myData)); |
*((long *)(*myMoovAtom + 0x04)) = EndianU32_NtoB(MovieAID); |
*((long *)(*myMoovAtom + 0x08)) = EndianU32_NtoB((2 * myAtomHeaderSize) + GetPtrSize(myData)); |
*((long *)(*myMoovAtom + 0x0C)) = EndianU32_NtoB(MovieDataRefAliasAID); |
*((long *)(*myMoovAtom + 0x10)) = EndianU32_NtoB((1 * myAtomHeaderSize) + GetPtrSize(myData)); |
*((long *)(*myMoovAtom + 0x14)) = EndianU32_NtoB(DataRefAID); |
// concatenate the data in myData onto the end of the movie atom |
myErr = PtrAndHand(myData, myMoovAtom, GetPtrSize(myData)); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// create the shortcut movie file |
// |
////////// |
myErr = QTShortCut_WriteHandleToFile(myMoovAtom, theFSSpecPtr); |
bail: |
if (myData != NULL) |
DisposePtr(myData); |
if (myMoovAtom != NULL) |
DisposeHandle(myMoovAtom); |
} |
return(myErr); |
} |
////////// |
// |
// QTShortCut_WriteHandleToFile |
// Write the data in the specified handle into the specified file; |
// if the file already exists, it is overwritten. |
// |
////////// |
OSErr QTShortCut_WriteHandleToFile (Handle theHandle, FSSpecPtr theFSSpecPtr) |
{ |
short myRefNum = 0; |
short myVolNum; |
long mySize = 0; |
OSErr myErr = paramErr; |
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, kShortcutFileCreator, kShortcutFileType, 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 // TARGET_OS_MAC |
bail: |
HUnlock(theHandle); |
return(myErr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14