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.
TimeCode Samples/AddTimeCodeƒ/AddTC.c
/* |
File: AddTC.c |
Contains: Time Code Functions. |
Written by: QT Engineering |
Copyright: © 1991-1994 by Apple Computer, Inc., all rights reserved. |
Change History (most recent first): |
<1> 12/7/94 khs changed the format of the file to the new look and feel |
To Do: |
*/ |
// INCLUDES |
#include <errors.h> |
#include <memory.h> |
#include <qdoffscreen.h> |
#include <palettes.h> |
#include <resources.h> |
#include <toolutils.h> |
#include <osutils.h> |
#include <files.h> |
#include <desk.h> |
#include <events.h> |
#include <osevents.h> |
#include <menus.h> |
#include <timer.h> |
#include <gestaltequ.h> |
#include <string.h> |
#include <strings.h> |
#include <fonts.h> |
#include <dialogs.h> |
#include <QuickDrawText.h> |
#include <stdio.h> |
#include <Components.h> |
#include <Movies.h> |
#include <QuickTimeComponents.h> |
// GLOBALS |
Str255 tcSrcName; |
Boolean tcDisplayTimeCode = false; |
Boolean tcDisplayBelowVideo = true; |
TimeScale tcTimeScale = 2997; |
TimeValue tcFrameDur = 100; |
long tcNumFrames = 30; |
Boolean tcDropFrameVal = true; |
Boolean tc24Hour = true; |
Boolean tcNegOK = false; |
Boolean tcIsNeg = false; |
long tcHours = 0; |
long tcMinutes = 0; |
long tcSeconds = 0; |
long tcFrames = 0; |
long tcCounterVal = 0; |
Boolean tcUseTimeCode = true; |
// FUNCTION PROTOTYPES |
extern OSErr GetMovie(Movie *theOutMovie, short *refnum, short *resid); |
extern OSErr InitEveryBody(void); |
extern void main(void); |
extern void AddTimeCode(Movie theMovie); |
extern void DeleteTimeCodes(Movie theMovie); |
extern Boolean GetTimeCodeOptions(void); |
extern void setDialogTextNumber(DialogPtr d, short itemNumber, long number); |
extern void setDialogTextString(DialogPtr d, short itemNumber, StringPtr str); |
extern Boolean validateDialogLong(DialogPtr d, short itemNumber, long *result); |
ControlHandle getDItemHandle(DialogPtr d, short itemNumber); |
ControlHandle getDItemRect(DialogPtr d, short itemNumber, Rect *r); |
// FUNCTIONS |
OSErr GetMovie(Movie *theOutMovie, short *refnum, short *resid) |
{ |
SFTypeList typeList; |
StandardFileReply reply; |
OSErr result = noErr; |
Movie theMovie = nil; |
typeList[0] = 'MooV'; |
StandardGetFile(nil, 1, typeList, &reply); |
if (!reply.sfGood) goto bail; |
result = OpenMovieFile(&reply.sfFile, refnum, 0); |
if (result != noErr) goto bail; |
*resid = 0; |
result = NewMovieFromFile(&theMovie,*refnum, resid, nil,0, nil); |
if (result != noErr) goto bail; |
bail: |
if (result) { |
DisposeMovie(theMovie); |
if (*refnum) CloseMovieFile(*refnum); |
*theOutMovie = nil; |
} |
else |
*theOutMovie = theMovie; |
return result; |
} |
OSErr InitEveryBody(void) |
{ |
InitGraf(&qd.thePort); |
InitFonts(); |
FlushEvents(0xffff,0); |
InitWindows(); |
InitMenus(); |
InitDialogs(0); |
TEInit(); |
InitCursor(); |
return EnterMovies(); |
} |
void main( void ) |
{ |
OSErr err; |
Movie theMovie; |
short movieResRef; |
short movieResID; |
MaxApplZone(); |
MoreMasters(); |
MoreMasters(); |
err = InitEveryBody(); |
if (err) return; |
err = GetMovie(&theMovie, &movieResRef, &movieResID ); |
if (!GetTimeCodeOptions()) |
return; |
// delete any existing TimeCode tracks |
DeleteTimeCodes( theMovie ); |
AddTimeCode( theMovie ); |
UpdateMovieResource( theMovie, movieResRef, movieResID, nil ); |
CloseMovieFile( movieResRef ); |
} |
#ifndef fieldOffset |
#define fieldOffset(type, field) ((short) &((type *) 0)->field) |
#endif |
void DeleteTimeCodes( Movie theMovie ) |
{ |
Track theTrack; |
theTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
while (theTrack) { |
DisposeMovieTrack( theTrack ); |
theTrack = GetMovieIndTrackType(theMovie, 1, TimeCodeMediaType, movieTrackMediaType); |
} |
} |
void AddTimeCode( Movie theMovie ) |
{ |
OSErr err; |
Track theTrack; |
Media theMedia; |
MediaHandler mh; |
long i; |
TimeCodeDef tcdef; |
TimeCodeRecord tcrec; |
UserData srcRef; |
Str63 tcStr; |
TimeValue movieDur; |
Rect curMovieBox; |
MatrixRecord mr; |
Fixed fwidth; |
Fixed fheight; |
long startingTrackCount; |
long flags; |
// calculate track height based on text |
TCTextOptions textOptions; |
FontInfo fontInfo; |
startingTrackCount = GetMovieTrackCount( theMovie ); |
GetMovieBox( theMovie, &curMovieBox ); |
OffsetRect( &curMovieBox, -curMovieBox.left, -curMovieBox.top ); |
theTrack = NewMovieTrack( theMovie, 20, 20, 0); // random track height |
theMedia = NewTrackMedia( theTrack, TimeCodeMediaType, GetMovieTimeScale(theMovie), nil, 0 ); |
mh = GetMediaHandler( theMedia ); |
// get display options to calc box height |
TCGetDisplayOptions( mh, &textOptions ); |
if (!tcUseTimeCode) { |
flags = tcCounter; |
} |
else { |
flags = 0; |
if (tcDropFrameVal) flags |= tcDropFrame; |
if (tcIsNeg) flags |= tcNegTimesOK; |
if (tc24Hour) flags |= tc24HourMax; |
} |
tcdef.flags = flags; |
tcdef.fTimeScale = tcTimeScale; |
tcdef.frameDuration = tcFrameDur; |
tcdef.numFrames = tcNumFrames; |
if (!tcUseTimeCode) { |
tcrec.c.counter = tcCounterVal; |
} |
else { |
tcrec.t.hours = tcHours; |
tcrec.t.minutes = tcMinutes; // negative flag is here |
tcrec.t.seconds = tcSeconds; |
tcrec.t.frames = tcFrames; |
if (tcIsNeg) tcrec.t.minutes |= tctNegFlag; |
} |
// use starting time to figure out dimensions of track |
err = TCTimeCodeToString( mh, &tcdef, &tcrec, tcStr); |
TextFont( textOptions.txFont ); |
TextFace( textOptions.txFace ); |
TextSize( textOptions.txSize ); |
GetFontInfo(&fontInfo); |
fheight = (long)(fontInfo.ascent + fontInfo.descent + 2)<<16; |
fwidth = (long)(StringWidth(tcStr) + 4)<<16; |
GetTrackMatrix( theTrack, &mr ); |
if (tcDisplayBelowVideo) { |
fwidth = (long)(curMovieBox.right - curMovieBox.left) << 16; |
SetTrackDimensions( theTrack, fwidth, fheight ); |
TranslateMatrix( &mr, 0, ((long)curMovieBox.bottom) << 16 ); |
} |
else { |
SetTrackDimensions( theTrack, fwidth, fheight ); |
TranslateMatrix( &mr, (Fixed)(curMovieBox.left + ((curMovieBox.right - curMovieBox.left - (fwidth>>16))>>1))<<16, |
(Fixed)(curMovieBox.bottom - (((fheight + (fheight>>1)) >> 16))) << 16 ); |
} |
SetTrackMatrix( theTrack, &mr ); |
SetTrackEnabled( theTrack, tcDisplayTimeCode?true:false ); |
TCSetTimeCodeFlags( mh, tcDisplayTimeCode?tcdfShowTimeCode:0, tcdfShowTimeCode ); |
err = BeginMediaEdits( theMedia ); |
{ |
TimeCodeDescriptionHandle tcdH; |
long **frameH; |
long size; |
Handle nameH; |
size = fieldOffset(TimeCodeDescription, srcRef); |
tcdH = (TimeCodeDescriptionHandle) NewHandleClear( size ); |
(**tcdH).descSize = size; |
(**tcdH).dataFormat = TimeCodeMediaType; |
(**tcdH).timeCodeDef = tcdef; |
err = NewUserData( &srcRef ); |
err = PtrToHand( &tcSrcName[1], &nameH, tcSrcName[0] ); |
err = AddUserDataText( srcRef, nameH, 'name', 1, langEnglish ); |
TCSetSourceRef( mh, tcdH, srcRef ); |
frameH = (long**)NewHandle( sizeof(long) ); |
err = TCTimeCodeToFrameNumber( mh, |
&(**tcdH).timeCodeDef, &tcrec, *frameH ); |
movieDur = GetMovieDuration(theMovie); |
// Since we created the track with the same timescale as the movie, |
// we don't need to convert the duration |
err = AddMediaSample( theMedia, (Handle)frameH, 0, GetHandleSize((Handle)frameH), |
movieDur, |
(SampleDescriptionHandle)tcdH, |
1, 0, 0 ); |
DisposeHandle( (Handle) tcdH ); |
DisposeHandle( (Handle) frameH ); |
DisposeHandle( nameH ); |
DisposeUserData( srcRef ); |
} |
err = EndMediaEdits( theMedia ); |
err = InsertMediaIntoTrack( theTrack, 0, 0, movieDur, fixed1 ); |
// let's record that this is timecode for all the current tracks |
for (i = 1; i <= startingTrackCount; i++) { |
err = AddTrackReference(GetMovieIndTrack(theMovie, i ), theTrack, TimeCodeMediaType, nil); |
} |
} |
#define diDialog 128 |
#define diSrcName 4 |
#define diDisplayTimeCode 5 |
#define diTimeScale 7 |
#define diFrameDur 9 |
#define diNumFrames 11 |
#define diUseTC 12 |
#define diUseCounter 13 |
#define diDropFrame 14 |
#define di24Hour (diDropFrame + 1) |
#define diNegOK (di24Hour + 1) |
#define diIsNeg (diNegOK + 2) |
#define diHours (diIsNeg + 1) |
#define diMinutes (diHours + 1) |
#define diSeconds (diMinutes + 1) |
#define diFrames (diSeconds + 1) |
#define diCounter 24 |
#define diBelowVideo 25 |
Boolean GetTimeCodeOptions(void) |
{ |
DialogPtr optionsDialog = nil; |
short itemHit = cancel; |
ControlHandle curCtl; |
Rect negRect; |
GrafPtr curPort; |
GetPort(&curPort); |
optionsDialog = GetNewDialog( diDialog, nil, (WindowPtr)-1L ); |
if (!optionsDialog) goto bail; |
SetDialogDefaultItem(optionsDialog, 1); |
SetDialogCancelItem(optionsDialog, 2); |
curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode ); |
SetCtlValue(curCtl,tcDisplayTimeCode); |
curCtl = getDItemHandle( optionsDialog, diBelowVideo ); |
SetCtlValue(curCtl,tcDisplayBelowVideo); |
curCtl = getDItemHandle( optionsDialog, diDropFrame ); |
SetCtlValue(curCtl,tcDropFrameVal); |
curCtl = getDItemHandle( optionsDialog, di24Hour ); |
SetCtlValue(curCtl,tc24Hour); |
curCtl = getDItemHandle( optionsDialog, diNegOK ); |
SetCtlValue(curCtl,tcNegOK); |
curCtl = getDItemRect( optionsDialog, diIsNeg, &negRect ); |
SetPort(optionsDialog); |
MoveTo(negRect.left+2, negRect.top+17); |
FrameRect(&negRect); |
TextSize(20); |
if (tcIsNeg) |
DrawString("\p-"); |
else |
DrawString("\p+"); |
TextSize(12); |
curCtl = getDItemHandle( optionsDialog, diUseTC ); |
SetCtlValue(curCtl,tcUseTimeCode?1:0); |
curCtl = getDItemHandle( optionsDialog, diUseCounter ); |
SetCtlValue(curCtl,tcUseTimeCode?0:1); |
setDialogTextNumber(optionsDialog, diTimeScale, tcTimeScale ); |
setDialogTextNumber(optionsDialog, diFrameDur, tcFrameDur ); |
setDialogTextNumber(optionsDialog, diNumFrames, tcNumFrames ); |
setDialogTextNumber(optionsDialog, diHours, tcHours ); |
setDialogTextNumber(optionsDialog, diMinutes, tcMinutes ); |
setDialogTextNumber(optionsDialog, diSeconds, tcSeconds ); |
setDialogTextNumber(optionsDialog, diFrames, tcFrames ); |
setDialogTextNumber(optionsDialog, diCounter, tcCounterVal ); |
setDialogTextString(optionsDialog, diSrcName, tcSrcName); |
noGood: |
do { |
ModalDialog( nil, &itemHit ); |
switch (itemHit) { |
case diDisplayTimeCode: |
curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode ); |
SetCtlValue(curCtl,!GetCtlValue(curCtl)); |
break; |
case diBelowVideo: |
curCtl = getDItemHandle( optionsDialog, diBelowVideo ); |
SetCtlValue(curCtl,!GetCtlValue(curCtl)); |
break; |
case diDropFrame: |
curCtl = getDItemHandle( optionsDialog, diDropFrame ); |
SetCtlValue(curCtl,!GetCtlValue(curCtl)); |
break; |
case di24Hour: |
curCtl = getDItemHandle( optionsDialog, di24Hour ); |
SetCtlValue(curCtl,!GetCtlValue(curCtl)); |
break; |
case diNegOK: |
curCtl = getDItemHandle( optionsDialog, diNegOK ); |
SetCtlValue(curCtl,!GetCtlValue(curCtl)); |
break; |
case diUseTC: |
curCtl = getDItemHandle( optionsDialog, diUseTC ); |
SetCtlValue(curCtl,1); |
curCtl = getDItemHandle( optionsDialog, diUseCounter ); |
SetCtlValue(curCtl,0); |
break; |
case diUseCounter: |
curCtl = getDItemHandle( optionsDialog, diUseCounter ); |
SetCtlValue(curCtl,1); |
curCtl = getDItemHandle( optionsDialog, diUseTC ); |
SetCtlValue(curCtl,0); |
break; |
case diIsNeg: |
tcIsNeg = !tcIsNeg; |
SetPort(optionsDialog); |
MoveTo(negRect.left+2, negRect.top+17); |
FrameRect(&negRect); |
InsetRect(&negRect,1,1); |
EraseRect(&negRect); |
InsetRect(&negRect,-1,-1); |
TextSize(20); |
if (tcIsNeg) |
DrawString("\p-"); |
else |
DrawString("\p+"); |
TextSize(12); |
break; |
} |
} while ((itemHit != ok) && (itemHit != cancel)); |
if (itemHit == ok) { |
curCtl = getDItemHandle(optionsDialog, diSrcName); |
GetIText((Handle)curCtl, tcSrcName); |
curCtl = getDItemHandle( optionsDialog, diDisplayTimeCode ); |
tcDisplayTimeCode = GetCtlValue(curCtl); |
curCtl = getDItemHandle( optionsDialog, diBelowVideo ); |
tcDisplayBelowVideo = GetCtlValue(curCtl); |
curCtl = getDItemHandle( optionsDialog, diDropFrame ); |
tcDropFrameVal = GetCtlValue(curCtl); |
curCtl = getDItemHandle( optionsDialog, di24Hour ); |
tc24Hour = GetCtlValue(curCtl); |
curCtl = getDItemHandle( optionsDialog, diNegOK ); |
tcNegOK = GetCtlValue(curCtl); |
curCtl = getDItemHandle( optionsDialog, diUseTC ); |
tcUseTimeCode = (GetCtlValue(curCtl) != 0); |
if (!validateDialogLong(optionsDialog, diTimeScale, &tcTimeScale)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diFrameDur, &tcFrameDur)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diNumFrames, &tcNumFrames)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diHours, &tcHours)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diMinutes, &tcMinutes)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diSeconds, &tcSeconds)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diFrames, &tcFrames)) |
goto noGood; |
if (!validateDialogLong(optionsDialog, diCounter, &tcCounterVal)) |
goto noGood; |
} |
DisposDialog(optionsDialog); |
bail: |
SetPort(curPort); |
return (itemHit == ok); |
} |
void setDialogTextNumber(DialogPtr d, short itemNumber, long number) |
{ |
Str255 theText; |
NumToString(number, theText); |
SetIText((Handle)getDItemHandle(d, itemNumber), theText); |
SelIText(d, itemNumber, 0, 32767); |
} |
void setDialogTextString(DialogPtr d, short itemNumber, StringPtr str) |
{ |
SetIText((Handle)getDItemHandle(d, itemNumber), str); |
SelIText(d, itemNumber, 0, 32767); |
} |
Boolean validateDialogLong(DialogPtr d, short itemNumber, long *result) |
{ |
Str255 theText; |
ControlHandle ch; |
Boolean digitFound; |
short i; |
ch = getDItemHandle(d, itemNumber); |
GetIText((Handle)ch, theText); |
digitFound = false; |
for (i = 1; i < theText[0]; i++) { |
if (theText[i] >= '0' && theText[i] <= '9') |
digitFound = true; |
else if (digitFound) { |
theText[0] = i-1; |
break; |
} |
else if (theText[i] != ' ') { |
SelIText(d, itemNumber, 0, 32767); |
SysBeep(1); |
return false; |
} |
} |
StringToNum( theText, result ); |
return true; |
} |
ControlHandle getDItemHandle(DialogPtr d, short itemNumber) |
{ |
short kind; |
ControlHandle ch; |
Rect r; |
GetDItem(d, itemNumber, &kind, (Handle *)&ch, &r); |
return(ch); |
} |
ControlHandle getDItemRect(DialogPtr d, short itemNumber, Rect *r) |
{ |
short kind; |
ControlHandle ch; |
GetDItem(d, itemNumber, &kind, (Handle *)&ch, r); |
return(ch); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14