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
////////// |
// |
// File: QTTimeCode.c |
// |
// Contains: QuickTime timecode media handler sample code. |
// |
// Written by: Tim Monroe |
// Based on AddTC.c sample code by QT Engineering and Apple Developer Technical Support. |
// |
// Copyright: © 1998-2000 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <9> 11/08/00 rtm removed "\p" escape sequences from QTTC_OptionsUserItemProcedure |
// <8> 10/15/00 rtm added QTTC_OptionsUserItemProcedure, so user item draws on Windows; |
// added font pop-up support to Windows |
// <7> 10/10/00 rtm added font pop-up menu (currently Mac only) |
// <6> 06/21/00 rtm minor tweaks |
// <5> 03/17/00 rtm made changes to get things running under CarbonLib |
// <4> 04/07/99 rtm modified QTTC_AddTimeCodeToMovie to add big-endian time code data to movie |
// (fixes problems on Windows) |
// <3> 06/05/98 rtm fixed track geometry calculations in QTTC_AddTimeCodeToMovie; other minor |
// cleanup here and there |
// <2> 05/21/98 rtm added QTTC_ShowStringToUser |
// <1> 05/18/98 rtm first file; conversion to personal coding style; updated to latest headers; |
// added ability to toggle timecode display in a movie containing a timecode track; |
// added ability to extract timecode values and source info; ported to Windows |
// |
// This source code shows how to add a timecode track to a movie. It also shows how to toggle the visibility |
// of a movie's timecode track and how to extract timecode values (and other info) from a timecode track. |
// |
////////// |
////////// |
// |
// header files |
// |
////////// |
#include "QTTimeCode.h" |
////////// |
// |
// global variables |
// |
////////// |
Str255 gSrcName; |
Str255 gFontName; // name of current font |
long gFontIndex = 1; // index in font pop-up menu of current font |
TimeScale gTimeScale = 2997; // typical for NTSC video (29.97 frames/sec) |
TimeValue gFrameDur = 100; // duration of a single frame |
long gNumFrames = 30; // frames per second |
Boolean gDisplayTimeCode = false; |
Boolean gDisplayBelowVideo = true; |
Boolean gDropFrameVal = true; |
Boolean g24Hour = true; |
Boolean gNegOK = false; |
Boolean gIsNeg = false; |
Boolean gUseTimeCode = true; // ue timecode (true) or counter (false)? |
long gHours = 0; |
long gMinutes = 0; |
long gSeconds = 0; |
long gFrames = 0; |
long gCounterVal = 0; |
UserItemUPP gOptionsUserItemProcUPP = NULL; // UPP to our options dialog user item procedure |
extern short gAppResFile; // file reference number for this application's resource file |
extern ModalFilterUPP gModalFilterUPP; // UPP to our custom dialog event filter |
////////// |
// |
// 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_GetTimeCodeOptions |
// Display our options dialog box and get the user's selections. |
// |
////////// |
Boolean QTTC_GetTimeCodeOptions (void) |
{ |
DialogPtr myDialog = NULL; |
short myItem = kStdCancelItemIndex; |
short myKind; |
ControlHandle myControl = NULL; |
Handle myHandle = NULL; |
MenuHandle myMenu = NULL; |
Rect myRect; |
GrafPtr myPort; |
GetPort(&myPort); |
myDialog = GetNewDialog(kTimeCodeDialogID, NULL, (WindowPtr)-1L); |
if (myDialog == NULL) |
goto bail; |
SetDialogDefaultItem(myDialog, kStdOkItemIndex); |
SetDialogCancelItem(myDialog, kStdCancelItemIndex); |
myControl = QTTC_GetDItemHandle(myDialog, kItemDisplayTimeCode); |
SetControlValue(myControl, gDisplayTimeCode); |
myControl = QTTC_GetDItemHandle(myDialog, kItemBelowVideo); |
SetControlValue(myControl, gDisplayBelowVideo); |
myControl = QTTC_GetDItemHandle(myDialog, kItemDropFrame); |
SetControlValue(myControl, gDropFrameVal); |
myControl = QTTC_GetDItemHandle(myDialog, kItem24Hour); |
SetControlValue(myControl, g24Hour); |
myControl = QTTC_GetDItemHandle(myDialog, kItemNegOK); |
SetControlValue(myControl, gNegOK); |
// set a user-item drawing procedure for the pos/neg box |
GetDialogItem(myDialog, kItemIsNeg, &myKind, &myHandle, &myRect); |
SetDialogItem(myDialog, kItemIsNeg, myKind, (Handle)gOptionsUserItemProcUPP, &myRect); |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseTC); |
SetControlValue(myControl, gUseTimeCode ? 1 : 0); |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseCounter); |
SetControlValue(myControl, gUseTimeCode ? 0 : 1); |
QTTC_SetDialogTextNumber(myDialog, kItemTimeScale, gTimeScale); |
QTTC_SetDialogTextNumber(myDialog, kItemFrameDur, gFrameDur); |
QTTC_SetDialogTextNumber(myDialog, kItemNumFrames, gNumFrames); |
QTTC_SetDialogTextNumber(myDialog, kItemHours, gHours); |
QTTC_SetDialogTextNumber(myDialog, kItemMinutes, gMinutes); |
QTTC_SetDialogTextNumber(myDialog, kItemSeconds, gSeconds); |
QTTC_SetDialogTextNumber(myDialog, kItemFrames, gFrames); |
QTTC_SetDialogTextNumber(myDialog, kItemCounter, gCounterVal); |
QTTC_SetDialogTextString(myDialog, kItemSrcName, gSrcName); |
// set the current value of the pop-up font menu |
myControl = QTTC_GetDItemRect(myDialog, kFontPopUpMenuControl, &myRect); |
if (myControl != NULL) { |
myMenu = MacGetMenu(kFontPopUpResID); |
if (myMenu != NULL) { |
#if ACCESSOR_CALLS_ARE_FUNCTIONS |
// insert the menu into the menu list |
MacInsertMenu(myMenu, kInsertHierarchicalMenu); |
SetControlPopupMenuHandle(myControl, myMenu); |
SetControlPopupMenuID(myControl, kFontPopUpResID); |
#else |
PopupPrivateData myPrivateData; |
// insert the menu into the menu list |
MacInsertMenu(myMenu, kInsertHierarchicalMenu); |
myPrivateData.mHandle = myMenu; |
myPrivateData.mID = kFontPopUpResID; |
(**(PopupPrivateDataHandle)(**myControl).contrlData) = myPrivateData; |
#endif |
// clean out existing menu |
while (CountMenuItems(myMenu)) |
DeleteMenuItem(myMenu, 1); |
// add in the available fonts |
AppendResMenu(myMenu, FOUR_CHAR_CODE('FONT')); |
SetControlMaximum(myControl, CountMenuItems(myMenu)); |
SetControlValue(myControl, gFontIndex); |
} |
} |
#if TARGET_API_MAC_CARBON |
MacShowWindow(GetDialogWindow(myDialog)); |
#else |
MacShowWindow(myDialog); |
#endif |
noGood: |
do { |
ModalDialog(gModalFilterUPP, &myItem); |
switch (myItem) { |
case kItemDisplayTimeCode: |
myControl = QTTC_GetDItemHandle(myDialog, kItemDisplayTimeCode); |
SetControlValue(myControl, !GetControlValue(myControl)); |
break; |
case kItemBelowVideo: |
myControl = QTTC_GetDItemHandle(myDialog, kItemBelowVideo); |
SetControlValue(myControl, !GetControlValue(myControl)); |
break; |
case kItemDropFrame: |
myControl = QTTC_GetDItemHandle(myDialog, kItemDropFrame); |
SetControlValue(myControl, !GetControlValue(myControl)); |
break; |
case kItem24Hour: |
myControl = QTTC_GetDItemHandle(myDialog, kItem24Hour); |
SetControlValue(myControl, !GetControlValue(myControl)); |
break; |
case kItemNegOK: |
myControl = QTTC_GetDItemHandle(myDialog, kItemNegOK); |
SetControlValue(myControl, !GetControlValue(myControl)); |
break; |
case kItemUseTC: |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseTC); |
SetControlValue(myControl, 1); |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseCounter); |
SetControlValue(myControl, 0); |
break; |
case kItemUseCounter: |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseCounter); |
SetControlValue(myControl, 1); |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseTC); |
SetControlValue(myControl, 0); |
break; |
case kItemIsNeg: |
gIsNeg = !gIsNeg; |
myControl = QTTC_GetDItemRect(myDialog, kItemIsNeg, &myRect); |
#if TARGET_API_MAC_CARBON |
InvalWindowRect(GetDialogWindow(myDialog), &myRect); |
#else |
InvalRect(&myRect); |
DrawDialog(myDialog); // force a redraw (necessary on Windows) |
#endif |
break; |
default: |
break; |
} |
} while ((myItem != kStdOkItemIndex) && (myItem != kStdCancelItemIndex)); |
if (myItem == kStdOkItemIndex) { |
myControl = QTTC_GetDItemHandle(myDialog, kItemSrcName); |
GetDialogItemText((Handle)myControl, gSrcName); |
myControl = QTTC_GetDItemHandle(myDialog, kItemDisplayTimeCode); |
gDisplayTimeCode = GetControlValue(myControl); |
myControl = QTTC_GetDItemHandle(myDialog, kItemBelowVideo); |
gDisplayBelowVideo = GetControlValue(myControl); |
myControl = QTTC_GetDItemHandle(myDialog, kItemDropFrame); |
gDropFrameVal = GetControlValue(myControl); |
myControl = QTTC_GetDItemHandle(myDialog, kItem24Hour); |
g24Hour = GetControlValue(myControl); |
myControl = QTTC_GetDItemHandle(myDialog, kItemNegOK); |
gNegOK = GetControlValue(myControl); |
myControl = QTTC_GetDItemHandle(myDialog, kItemUseTC); |
gUseTimeCode = (GetControlValue(myControl) != 0); |
myControl = QTTC_GetDItemHandle(myDialog, kFontPopUpMenuControl); |
if (myControl != NULL) { |
MenuHandle myMenu = NULL; |
#if ACCESSOR_CALLS_ARE_FUNCTIONS |
myMenu = GetControlPopupMenuHandle(myControl); |
#else |
myMenu = (**((PopupPrivateDataHandle)(**myControl).contrlData)).mHandle; |
#endif |
gFontIndex = GetControlValue(myControl); |
GetMenuItemText(myMenu, gFontIndex, gFontName); |
} |
if (!QTTC_ValidateDialogLong(myDialog, kItemTimeScale, &gTimeScale)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemFrameDur, &gFrameDur)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemNumFrames, &gNumFrames)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemHours, &gHours)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemMinutes, &gMinutes)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemSeconds, &gSeconds)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemFrames, &gFrames)) |
goto noGood; |
if (!QTTC_ValidateDialogLong(myDialog, kItemCounter, &gCounterVal)) |
goto noGood; |
} |
bail: |
// remove the pop-up menu from the menu list |
if (myMenu != NULL) |
#if ACCESSOR_CALLS_ARE_FUNCTIONS |
MacDeleteMenu(GetMenuID(myMenu)); |
#else |
MacDeleteMenu((**myMenu).menuID); |
#endif |
if (myDialog != NULL) |
DisposeDialog(myDialog); |
MacSetPort(myPort); |
return(myItem == kStdOkItemIndex); |
} |
////////// |
// |
// QTTC_OptionsUserItemProcedure |
// A user-item procedure to draw a box in the options dialog box. |
// |
////////// |
PASCAL_RTN void QTTC_OptionsUserItemProcedure (DialogPtr theDialog, short theItem) |
{ |
Handle myItemHandle = NULL; |
Rect myRect; |
ControlHandle myControl = NULL; |
StringPtr mySign = NULL; |
if (theItem != kItemIsNeg) |
return; |
MacSetPort(GetDialogPort(theDialog)); |
myControl = QTTC_GetDItemRect(theDialog, kItemIsNeg, &myRect); |
MoveTo(myRect.left + 2, myRect.top + 17); |
MacFrameRect(&myRect); |
MacInsetRect(&myRect, 1, 1); |
EraseRect(&myRect); |
MacInsetRect(&myRect, -1, -1); |
TextSize(kTextBigSize); |
if (gIsNeg) |
mySign = QTUtils_ConvertCToPascalString("-"); |
else |
mySign = QTUtils_ConvertCToPascalString("+"); |
DrawString(mySign); |
TextSize(kTextRegSize); |
free(mySign); |
} |
////////// |
// |
// QTTC_SetDialogTextNumber |
// Set and highlight the text of a dialog item. |
// |
////////// |
void QTTC_SetDialogTextNumber (DialogPtr theDialog, short theItem, long theNumber) |
{ |
Str255 myText; |
NumToString(theNumber, myText); |
SetDialogItemText((Handle)QTTC_GetDItemHandle(theDialog, theItem), myText); |
SelectDialogItemText(theDialog, theItem, 0, 32767); |
} |
////////// |
// |
// QTTC_SetDialogTextString |
// Set and highlight the text of a dialog item. |
// |
////////// |
void QTTC_SetDialogTextString (DialogPtr theDialog, short theItem, StringPtr theString) |
{ |
SetDialogItemText((Handle)QTTC_GetDItemHandle(theDialog, theItem), theString); |
SelectDialogItemText(theDialog, theItem, 0, 32767); |
} |
////////// |
// |
// QTTC_ValidateDialogLong |
// Validate a long value. |
// |
////////// |
Boolean QTTC_ValidateDialogLong (DialogPtr theDialog, short theItem, long *theResult) |
{ |
Str255 myText; |
ControlHandle myHandle; |
Boolean IsDigitFound = false; |
short myIndex; |
myHandle = QTTC_GetDItemHandle(theDialog, theItem); |
GetDialogItemText((Handle)myHandle, myText); |
for (myIndex = 1; myIndex < myText[0]; myIndex++) { |
if (myText[myIndex] >= '0' && myText[myIndex] <= '9') { |
IsDigitFound = true; |
} else if (IsDigitFound) { |
myText[0] = myIndex - 1; |
break; |
} else if (myText[myIndex] != ' ') { |
SelectDialogItemText(theDialog, theItem, 0, 32767); |
SysBeep(1); |
return(false); |
} |
} |
StringToNum(myText, theResult); |
return(true); |
} |
////////// |
// |
// QTTC_GetDItemHandle |
// Get the handle of the specified dialog item. |
// |
////////// |
ControlHandle QTTC_GetDItemHandle (DialogPtr theDialog, short theItem) |
{ |
short myKind; |
ControlHandle myHandle; |
Rect myRect; |
GetDialogItem(theDialog, theItem, &myKind, (Handle *)&myHandle, &myRect); |
return(myHandle); |
} |
////////// |
// |
// QTTC_GetDItemRect |
// Get the rectangle surrounding the specified dialog item. |
// |
////////// |
ControlHandle QTTC_GetDItemRect (DialogPtr theDialog, short theItem, Rect *theRect) |
{ |
short myKind; |
ControlHandle myHandle; |
GetDialogItem(theDialog, theItem, &myKind, (Handle *)&myHandle, theRect); |
return(myHandle); |
} |
////////// |
// |
// 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) |
QTTC_ShowStringToUser(myString); |
} |
} |
} |
////////// |
// |
// 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); |
QTTC_ShowStringToUser(myString); |
DisposeUserData(myUserData); |
} |
} |
} |
////////// |
// |
// QTTC_ShowStringToUser |
// Display a string in an alert box. |
// |
////////// |
void QTTC_ShowStringToUser (StringPtr theString) |
{ |
short mySavedResFile; |
// get the current resource file and set the application's resource file |
mySavedResFile = CurResFile(); |
UseResFile(gAppResFile); |
ParamText(theString, NULL, NULL, NULL); |
Alert(kTimeCodeAlertID, NULL); |
// restore the original resource file |
UseResFile(mySavedResFile); |
} |
////////// |
// |
// 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); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14