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.
QTTimeCode.c
// ************ This file is for reference only and NOT used in this Sample ************ |
// This file only contains the older C Utility functions that call the QuickTime |
// Timecode Media Handler - all other support functions have |
// been removed as they are all deprecated. |
/* |
© Copyright 2000 - 2007 Apple Computer, Inc. All rights reserved. |
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. |
*/ |
// ************ This file is for reference only and NOT used in this Sample ************ |
// This file only contains the older C Utility functions that call the QuickTime |
// Timecode Media Handler - all other support functions have |
// been removed as they are all deprecated. |
/////////// |
// |
// QTTC_DeleteTimeCodeTracks |
// Remove all existing timecode tracks from the specified movie. |
// |
////////// |
void QTTC_DeleteTimeCodeTracks (Movie theMovie) |
{ |
Track myTrack = NULL; |
myTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
while (myTrack != NULL) { |
DisposeMovieTrack(myTrack); |
myTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
} |
} |
////////// |
// |
// QTTC_AddTimeCodeToMovie |
// Add a timecode track to the specified movie. |
// |
////////// |
OSErr QTTC_AddTimeCodeToMovie (Movie theMovie, OSType theType) |
{ |
Track myTypeTrack = NULL; |
Track myTrack = NULL; |
Media myMedia = NULL; |
MediaHandler myHandler = NULL; |
TimeCodeDef myTCDef; |
TimeCodeRecord myTCRec; |
Str63 myString; |
TimeValue myDuration; |
MatrixRecord myMatrix; |
Fixed myWidth; |
Fixed myHeight; |
Fixed myTCHeight; |
long myFlags = 0L; |
TCTextOptions myTextOptions; |
FontInfo myFontInfo; |
TimeCodeDescriptionHandle myDesc = NULL; |
long **myFrameHandle; |
OSErr myErr = noErr; |
////////// |
// |
// find the target track |
// |
////////// |
// get the (first) track of the specified type; this track determines the width of the new timecode track |
myTypeTrack = GetMovieIndTrackType(theMovie, 1, theType, movieTrackMediaType); |
if (myTypeTrack == NULL) { |
myErr = trackNotInMovie; |
goto bail; |
} |
// get the dimensions of the target track |
GetTrackDimensions(myTypeTrack, &myWidth, &myHeight); |
////////// |
// |
// create the timecode track and media |
// |
////////// |
myTrack = NewMovieTrack(theMovie, myWidth, kTimeCodeTrackSize, kNoVolume); |
if (myTrack == NULL) |
goto bail; |
myMedia = NewTrackMedia(myTrack, TimeCodeMediaType, GetMovieTimeScale(theMovie), NULL, 0); |
if (myMedia == NULL) |
goto bail; |
myHandler = GetMediaHandler(myMedia); |
if (myHandler == NULL) |
goto bail; |
////////// |
// |
// fill in a timecode definition structure; this becomes part of the timecode description |
// |
////////// |
// set the timecode format information flags |
if (gUseTimeCode) { |
myFlags = 0L; |
if (gDropFrameVal) |
myFlags |= tcDropFrame; |
if (gIsNeg) |
myFlags |= tcNegTimesOK; |
if (g24Hour) |
myFlags |= tc24HourMax; |
} else { |
myFlags = tcCounter; |
} |
myTCDef.flags = myFlags; |
myTCDef.fTimeScale = gTimeScale; |
myTCDef.frameDuration = gFrameDur; |
myTCDef.numFrames = gNumFrames; |
////////// |
// |
// fill in a timecode record |
// |
////////// |
if (gUseTimeCode) { |
myTCRec.t.hours = (UInt8)gHours; |
myTCRec.t.minutes = (UInt8)gMinutes; // negative flag is here |
myTCRec.t.seconds = (UInt8)gSeconds; |
myTCRec.t.frames = (UInt8)gFrames; |
if (gIsNeg) |
myTCRec.t.minutes |= tctNegFlag; |
} else { |
myTCRec.c.counter = gCounterVal; |
} |
////////// |
// |
// figure out the timecode track geometry |
// |
////////// |
// get display options to calculate box height |
TCGetDisplayOptions(myHandler, &myTextOptions); |
GetFNum(gFontName, &myTextOptions.txFont); |
TCSetDisplayOptions(myHandler, &myTextOptions); |
// use the starting time to figure out the dimensions of track |
TCTimeCodeToString(myHandler, &myTCDef, &myTCRec, myString); |
TextFont(myTextOptions.txFont); |
TextFace(myTextOptions.txFace); |
TextSize(myTextOptions.txSize); |
GetFontInfo(&myFontInfo); |
// calculate track width and height based on text |
myTCHeight = FixRatio(myFontInfo.ascent + myFontInfo.descent + 2, 1); |
SetTrackDimensions(myTrack, myWidth, myTCHeight); |
GetTrackMatrix(myTrack, &myMatrix); |
if (gDisplayBelowVideo) |
TranslateMatrix(&myMatrix, 0, myHeight); |
SetTrackMatrix(myTrack, &myMatrix); |
SetTrackEnabled(myTrack, gDisplayTimeCode ? true : false); |
TCSetTimeCodeFlags(myHandler, gDisplayTimeCode ? tcdfShowTimeCode : 0, tcdfShowTimeCode); |
////////// |
// |
// edit the track media |
// |
////////// |
myErr = BeginMediaEdits(myMedia); |
if (myErr == noErr) { |
long mySize; |
UserData myUserData; |
////////// |
// |
// create and configure a new timecode description handle |
// |
////////// |
mySize = sizeof(TimeCodeDescription); |
myDesc = (TimeCodeDescriptionHandle)NewHandleClear(mySize); |
if (myDesc == NULL) |
goto bail; |
(**myDesc).descSize = mySize; |
(**myDesc).dataFormat = TimeCodeMediaType; |
(**myDesc).timeCodeDef = myTCDef; |
////////// |
// |
// set the source identification information |
// |
////////// |
// the source identification information for a timecode track is stored |
// in a user data item of type TCSourceRefNameType |
myErr = NewUserData(&myUserData); |
if (myErr == noErr) { |
Handle myNameHandle = NULL; |
myErr = PtrToHand(&gSrcName[1], &myNameHandle, gSrcName[0]); |
if (myErr == noErr) { |
myErr = AddUserDataText(myUserData, myNameHandle, TCSourceRefNameType, 1, langEnglish); |
if (myErr == noErr) |
TCSetSourceRef(myHandler, myDesc, myUserData); |
} |
if (myNameHandle != NULL) |
DisposeHandle(myNameHandle); |
DisposeUserData(myUserData); |
} |
////////// |
// |
// add a sample to the timecode track |
// |
// each sample in a timecode track provides timecode information for a span of movie time; |
// here, we add a single sample that spans the entire movie duration |
// |
////////// |
// the sample data contains a frame number that identifies one or more content frames |
// that use the timecode; this value (a long integer) identifies the first frame that |
// uses the timecode |
myFrameHandle = (long **)NewHandle(sizeof(long)); |
if (myFrameHandle == NULL) |
goto bail; |
myErr = TCTimeCodeToFrameNumber(myHandler, &(**myDesc).timeCodeDef, &myTCRec, *myFrameHandle); |
// the data in the timecode track must be big-endian |
**myFrameHandle = EndianS32_NtoB(**myFrameHandle); |
myDuration = GetMovieDuration(theMovie); |
// since we created the track with the same timescale as the movie, |
// we don't need to convert the duration |
myErr = AddMediaSample(myMedia, (Handle)myFrameHandle, 0, GetHandleSize((Handle)myFrameHandle), myDuration, (SampleDescriptionHandle)myDesc, 1, 0, 0); |
if (myErr != noErr) |
goto bail; |
} |
myErr = EndMediaEdits(myMedia); |
if (myErr != noErr) |
goto bail; |
myErr = InsertMediaIntoTrack(myTrack, 0, 0, myDuration, fixed1); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// create a track reference from the target track to the timecode track |
// |
////////// |
myErr = AddTrackReference(myTypeTrack, myTrack, TimeCodeMediaType, NULL); |
bail: |
if (myDesc != NULL) |
DisposeHandle((Handle)myDesc); |
if (myFrameHandle != NULL) |
DisposeHandle((Handle)myFrameHandle); |
return(myErr); |
} |
////////// |
// |
// QTTC_ShowCurrentTimeCode |
// Show (in an alert box) the timecode value for the current movie time. |
// |
////////// |
void QTTC_ShowCurrentTimeCode (Movie theMovie) |
{ |
MediaHandler myHandler = NULL; |
HandlerError myErr = noErr; |
TimeCodeDef myTCDef; |
TimeCodeRecord myTCRec; |
myHandler = QTTC_GetTimeCodeMediaHandler(theMovie); |
if (myHandler != NULL) { |
// get the timecode for the current movie time |
myErr = TCGetCurrentTimeCode(myHandler, NULL, &myTCDef, &myTCRec, NULL); |
if (myErr == noErr) { |
Str255 myString; |
myErr = TCTimeCodeToString(myHandler, &myTCDef, &myTCRec, myString); |
if (myErr == noErr) |
// do something with the string |
} |
} |
} |
////////// |
// |
// QTTC_ShowTimeCodeSource |
// Show (in an alert box) the timecode source for the specified movie. |
// |
////////// |
void QTTC_ShowTimeCodeSource (Movie theMovie) |
{ |
MediaHandler myHandler = NULL; |
HandlerError myErr = noErr; |
UserData myUserData; |
myHandler = QTTC_GetTimeCodeMediaHandler(theMovie); |
if (myHandler != NULL) { |
// get the timecode source for the current movie time |
myErr = TCGetCurrentTimeCode(myHandler, NULL, NULL, NULL, &myUserData); |
if (myErr == noErr) { |
Str255 myString = " [No source name!]"; |
Handle myNameHandle = NewHandleClear(0); |
GetUserDataText(myUserData, myNameHandle, TCSourceRefNameType, 1, langEnglish); |
if (GetHandleSize(myNameHandle) > 0) { |
BlockMove(*myNameHandle, &myString[1], GetHandleSize(myNameHandle)); |
myString[0] = GetHandleSize(myNameHandle); |
} |
if (myNameHandle != NULL) |
DisposeHandle(myNameHandle); |
// do something with the string |
DisposeUserData(myUserData); |
} |
} |
} |
////////// |
// |
// QTTC_ToggleTimeCodeDisplay |
// Toggle the current state of timecode display. |
// |
////////// |
void QTTC_ToggleTimeCodeDisplay (MovieController theMC) |
{ |
Movie myMovie = MCGetMovie(theMC); |
Track myTrack = NULL; |
MediaHandler myHandler = NULL; |
long myFlags = 0L; |
// get the (first) timecode track in the specified movie |
myTrack = GetMovieIndTrackType(myMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
if (myTrack != NULL) { |
// get the timecode track's media handler |
myHandler = QTTC_GetTimeCodeMediaHandler(myMovie); |
if (myHandler != NULL) { |
// toggle the show-timecode flag |
TCGetTimeCodeFlags(myHandler, &myFlags); |
myFlags ^= tcdfShowTimeCode; |
TCSetTimeCodeFlags(myHandler, myFlags, tcdfShowTimeCode); |
// toggle the track enabled state |
SetTrackEnabled(myTrack, !GetTrackEnabled(myTrack)); |
// now tell the movie controller the movie has changed, |
// so that the movie rectangle gets updated correctly |
MCMovieChanged(theMC, myMovie); |
} |
} |
} |
////////// |
// |
// QTTC_GetTimeCodeMediaHandler |
// Get the media handler for the first timecode track in the specified movie. |
// |
////////// |
MediaHandler QTTC_GetTimeCodeMediaHandler (Movie theMovie) |
{ |
Track myTrack = NULL; |
Media myMedia = NULL; |
MediaHandler myHandler = NULL; |
// get the (first) timecode track in the specified movie |
myTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
if (myTrack != NULL) { |
// get the timecode track's media and media handler |
myMedia = GetTrackMedia(myTrack); |
if (myMedia != NULL) |
myHandler = GetMediaHandler(myMedia); |
} |
return(myHandler); |
} |
////////// |
// |
// QTTC_MovieHasTimeCodeTrack |
// Determine whether the specified movie contains a timecode track. |
// |
////////// |
Boolean QTTC_MovieHasTimeCodeTrack(Movie theMovie) |
{ |
return(GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType) != NULL); |
} |
////////// |
// |
// QTUtils_DeleteAllReferencesToTrack |
// Delete all existing track references to the specified track. |
// |
////////// |
OSErr QTUtils_DeleteAllReferencesToTrack (Track theTrack) |
{ |
Movie myMovie = NULL; |
Track myTrack = NULL; |
long myTrackCount = 0L; |
long myTrRefCount = 0L; |
long myTrackIndex; |
long myTrRefIndex; |
OSErr myErr = noErr; |
myMovie = GetTrackMovie(theTrack); |
if (myMovie == NULL) |
return(paramErr); |
// iterate thru all the tracks in the movie (that are different from the specified track) |
myTrackCount = GetMovieTrackCount(myMovie); |
for (myTrackIndex = 1; myTrackIndex <= myTrackCount; myTrackIndex++) { |
myTrack = GetMovieIndTrack(myMovie, myTrackIndex); |
if ((myTrack != NULL) && (myTrack != theTrack)) { |
OSType myType = 0L; |
// iterate thru all track reference types contained in the current track |
myType = GetNextTrackReferenceType(myTrack, myType); |
while (myType != 0L) { |
// iterate thru all track references of the current type; |
// note that we count down to 1, since DeleteTrackReference will cause |
// any higher-indexed track references to be renumbered |
myTrRefCount = GetTrackReferenceCount(myTrack, myType); |
for (myTrRefIndex = myTrRefCount; myTrRefIndex >= 1; myTrRefIndex--) { |
Track myRefTrack = NULL; |
myRefTrack = GetTrackReference(myTrack, myType, myTrRefIndex); |
if (myRefTrack == theTrack) |
myErr = DeleteTrackReference(myTrack, myType, myTrRefIndex); |
} |
myType = GetNextTrackReferenceType(myTrack, myType); |
} |
} |
} |
return(myErr); |
} |
// ************ This file is for reference only and NOT used in this Sample ************ |
// This file only contains the older C Utility functions that call the QuickTime |
// Timecode Media Handler - all other support functions have |
// been removed as they are all deprecated. |
Copyright © 2007 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2007-09-19