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.
AddFlashActions.c
////////// |
// |
// File: AddFlashActions.c |
// |
// Contains: Sample code for adding actions to a Flash track in a movie. |
// |
// Written by: Tim Monroe |
// Based on existing code by Bill Wright. |
// |
// Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
// <3> 08/24/01 rtm finally fully working |
// <2> 07/20/99 rtm further work; removed reliance on AtomUtilities.c |
// <1> 07/16/99 rtm first file from bw; revised to sample code coding style |
// |
////////// |
#include "AddFlashActions.h" |
extern FlashParserStruct gFlashParserData; |
static long gFlashConditions[] = { |
kIdleToOverUp, |
kOverUpToIdle, |
kOverUpToOverDown, |
kOverDownToOverUp, |
kOverDownToOutDown, |
kOutDownToOverDown, |
kOutDownToIdle, |
kIdleToOverDown, |
kOverDownToIdle |
}; |
////////// |
// |
// main/WinMain |
// The main function for this application. |
// |
////////// |
#if TARGET_OS_MAC |
void main (void) |
#elif TARGET_OS_WIN32 |
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR theCmdLine, int nCmdShow) |
#endif |
{ |
OSType myTypeList[1] = {MovieFileType}; |
StandardFileReply myReply; |
OSErr myErr = noErr; |
#if TARGET_OS_WIN32 |
InitializeQTML(0L); // initialize QuickTime Media Layer |
#endif |
#if TARGET_OS_MAC |
MaxApplZone(); // init everything |
InitGraf(&qd.thePort); |
InitFonts(); |
FlushEvents(everyEvent, 0); |
InitWindows(); |
InitMenus(); |
InitDialogs(NULL); |
TEInit(); |
InitCursor(); |
#endif |
myErr = EnterMovies(); |
if (myErr != noErr) |
goto bail; |
// elicit a movie file from the user |
StandardGetFile(NULL, 1, myTypeList, &myReply); |
// add some wired actions to it, if it's a movie with a Flash track |
if (myReply.sfGood) |
AddFLAct_AddWiredActionsToFlashMovie(&myReply.sfFile); |
bail: |
ExitMovies(); |
#if TARGET_OS_WIN32 |
// terminate the QuickTime Media Layer |
TerminateQTML(); |
return(1); |
#endif |
#if TARGET_OS_MAC |
return; |
#endif |
} |
////////// |
// |
// AddFLAct_CreateButtonActionContainer |
// Return, through the theActions parameter, an atom container that contains a button action. |
// |
////////// |
static OSErr AddFLAct_CreateButtonActionContainer (QTAtomContainer *theActions) |
{ |
QTAtom myEventAtom = 0; |
QTAtom myActionAtom = 0; |
long myAction; |
Fixed myRate; |
OSErr myErr = noErr; |
myErr = QTNewAtomContainer(theActions); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add an action that sets the movie rate to 1 on an up-to-down mouse-click event |
// |
////////// |
myErr = QTInsertChild(*theActions, kParentAtomIsContainer, kQTEventType, kOverUpToOverDown, kIndexOne, kZeroDataLength, NULL, &myEventAtom); |
if (myErr != noErr) |
goto bail; |
myErr = QTInsertChild(*theActions, myEventAtom, kAction, kIndexOne, kIndexOne, kZeroDataLength, NULL, &myActionAtom); |
if (myErr != noErr) |
goto bail; |
myAction = EndianS32_NtoB(kActionMovieSetRate); |
myErr = QTInsertChild(*theActions, myActionAtom, kWhichAction, kIndexOne, kIndexOne, sizeof(long), &myAction, NULL); |
if (myErr != noErr) |
goto bail; |
myRate = EndianU32_NtoB(fixed1); |
myErr = QTInsertChild(*theActions, myActionAtom, kActionParameter, kIndexOne, kIndexOne, sizeof(Fixed), &myRate, NULL); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add an action that sets the movie rate to 0 on a down-to-up mouse-click event |
// |
////////// |
myErr = QTInsertChild(*theActions, kParentAtomIsContainer, kQTEventType, kOverDownToOverUp, kIndexOne, kZeroDataLength, NULL, &myEventAtom); |
if (myErr != noErr) |
goto bail; |
myErr = QTInsertChild(*theActions, myEventAtom, kAction, kIndexOne, kIndexOne, kZeroDataLength, NULL, &myActionAtom); |
if (myErr != noErr) |
goto bail; |
myAction = EndianS32_NtoB(kActionMovieSetRate); |
myErr = QTInsertChild(*theActions, myActionAtom, kWhichAction, kIndexOne, kIndexOne, sizeof(long), &myAction, NULL); |
if (myErr != noErr) |
goto bail; |
myRate = EndianU32_NtoB(0); |
myErr = QTInsertChild(*theActions, myActionAtom, kActionParameter, kIndexOne, kIndexOne, sizeof(Fixed), &myRate, NULL); |
bail: |
return(myErr); |
} |
////////// |
// |
// AddFLAct_CreateFrameLoadedActionContainer |
// Return, through the theActions parameter, an atom container that contains a frame-loaded event action. |
// |
////////// |
static OSErr AddFLAct_CreateFrameLoadedActionContainer (QTAtomContainer *theActions) |
{ |
QTAtom myEventAtom = 0; |
QTAtom myActionAtom = 0; |
long myAction; |
QTAtomID myCursorID; |
OSErr myErr = noErr; |
myErr = QTNewAtomContainer(theActions); |
if (myErr != noErr) |
goto bail; |
myErr = QTInsertChild(*theActions, kParentAtomIsContainer, kQTEventFrameLoaded, kIndexOne, kIndexOne, kZeroDataLength, NULL, &myEventAtom); |
if (myErr != noErr) |
goto bail; |
myErr = QTInsertChild(*theActions, myEventAtom, kAction, kIndexOne, kIndexOne, kZeroDataLength, NULL, &myActionAtom); |
if (myErr != noErr) |
goto bail; |
myAction = EndianS32_NtoB(kActionTrackSetCursor); |
myErr = QTInsertChild(*theActions, myActionAtom, kWhichAction, kIndexOne, kIndexOne, sizeof(long), &myAction, NULL); |
if (myErr != noErr) |
goto bail; |
myCursorID = EndianS32_NtoB(kQTCursorOpenHand); |
myErr = QTInsertChild(*theActions, myActionAtom, kActionParameter, kIndexOne, kIndexOne, sizeof(QTAtomID), &myCursorID, NULL); |
bail: |
return(myErr); |
} |
////////// |
// |
// AddFLAct_SetWiredActionToButton |
// Modify the flash sample to insert or remove actions for the specified mouse condition for the specified button. |
// |
////////// |
static void AddFLAct_SetWiredActionToButton (Handle theSample, long theButtonID, U16 theCondition, QTAtomContainer theAction) |
{ |
short myActionCount; |
short myActionIndex; |
U32 myOffset; |
U32 myStart; |
U32 myActionOffset; |
U32 myActionLength; |
U32 myDataLength; |
U32 myStartActionOffset; |
U32 myOffsetLocation; |
U32 myButtonRecordLength; |
U32 myPrevOffset; |
U32 myPrevStart; |
U16 myLocalCondition; |
long myActionHandleSize; |
long myDataHandleSize; |
long myShortenAmount; |
long myIncreaseAmount; |
long myMoveAmount; |
long myDifference; |
U8 myActionCode; |
U8 *myArray; |
Ptr myPtr = NULL; |
Boolean isFound = false; |
OSErr myErr = noErr; |
gFlashParserData.m_theData = theSample; |
HLock(theSample); |
myOffset = GetOffsetForButton(theButtonID); |
gFlashParserData.m_fileBuf = (U8 *)*theSample; |
gFlashParserData.m_filePos = myOffset; |
(void)GetTag(); |
gFlashParserData.m_filePos += sizeof(U16); // step over tagID |
gFlashParserData.m_filePos += sizeof(U8); // step over menu flag |
myOffsetLocation = gFlashParserData.m_filePos; |
myButtonRecordLength = 0; |
myActionCount = 0; |
myOffset = (U32)GetWord(); |
if (myOffset == 0) { |
// no current actions |
myStartActionOffset = gFlashParserData.m_tagEnd; |
myButtonRecordLength = gFlashParserData.m_tagEnd - myOffsetLocation; |
} else { |
myActionOffset = 0; |
gFlashParserData.m_filePos += myOffset - sizeof(U16); |
myStartActionOffset = gFlashParserData.m_filePos; |
myPrevStart = 0; |
// locate current actions for the specified condition |
while (gFlashParserData.m_filePos < gFlashParserData.m_tagEnd) { |
myStart = gFlashParserData.m_filePos; |
myActionCount++; |
myOffset = (U32)GetWord(); |
myLocalCondition = GetWord(); |
myActionCode = GetByte(); |
if ((myActionCode == sactionWiredActions) && (myLocalCondition == theCondition)) { |
myActionIndex = myActionCount; |
myActionOffset = myStart; |
myActionLength = myOffset; |
myPrevOffset = myPrevStart; |
myDataLength = (U32)GetWord(); |
isFound = true; |
} |
if (!myOffset) |
break; |
myPrevStart = myStart; |
gFlashParserData.m_filePos = myStart + myOffset; |
} |
} |
HUnlock(theSample); |
myDataHandleSize = GetHandleSize(theSample); |
if (isFound) { |
if (theAction != NULL) { |
// replace with new data |
myActionHandleSize = GetHandleSize((Handle)theAction); |
if (myActionHandleSize == myDataLength) { |
// just replace |
HLock(theSample); |
HLock((Handle)theAction); |
BlockMove( *theAction, |
(*theSample + myActionOffset + sizeof(U16) + sizeof(U16) + sizeof(U8) + sizeof(U16)), |
myActionHandleSize); |
HUnlock((Handle)theAction); |
HUnlock(theSample); |
} else { |
myMoveAmount = myDataHandleSize - (myActionOffset + myActionLength); |
if (myActionHandleSize < myDataLength) { |
// compact space for new data |
myShortenAmount = myDataLength - myActionHandleSize; |
myDifference = -myShortenAmount; |
HLock(theSample); |
BlockMove( *theSample + (myActionOffset + myActionLength), |
*theSample + (myActionOffset + myActionLength - myShortenAmount), |
myMoveAmount); |
HUnlock(theSample); |
myDataHandleSize -= myShortenAmount; |
SetHandleSize(theSample, myDataHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
} else { |
// expand space for new data |
myIncreaseAmount = myActionHandleSize - myDataLength; |
myDataHandleSize += myIncreaseAmount; |
myDifference = myIncreaseAmount; |
SetHandleSize(theSample, myDataHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
BlockMove( *theSample + (myActionOffset + myActionLength), |
(*theSample + myActionOffset + myActionLength + myIncreaseAmount), |
myMoveAmount); |
HUnlock(theSample); |
} |
HLock(theSample); |
HLock((Handle)theAction); |
// patch in action length |
myArray = (U8 *)*theSample + myActionOffset; |
myActionLength += myDifference; |
myArray[0] = myActionLength & 0xFF; |
myArray[1] = (myActionLength >> 8) & 0xFF; |
// patch in action container length |
myArray = (U8 *)*theSample + myActionOffset + sizeof(U16) + sizeof(U16) + sizeof(U8); |
myArray[0] = myActionHandleSize & 0xFF; |
myArray[1] = (myActionHandleSize >> 8) & 0xFF; |
// copy new data |
BlockMove( *theAction, |
(*theSample + myActionOffset + sizeof(U16) + sizeof(U16) + sizeof(U8) + sizeof(U16)), |
myActionHandleSize); |
HUnlock((Handle)theAction); |
HUnlock(theSample); |
// adjust tag length and data stream header length |
SetNewHeaderLengthTagLength(myDifference, myDifference); |
} |
} else { |
// remove old data |
HLock(theSample); |
if (myActionIndex == myActionCount) { // last action |
if (myActionCount == 1) { |
// need to clear all action data |
myMoveAmount = myDataHandleSize - gFlashParserData.m_tagEnd; |
BlockMove(*theSample + gFlashParserData.m_tagEnd, *theSample + myStartActionOffset, myMoveAmount); |
myShortenAmount = gFlashParserData.m_tagEnd - myStartActionOffset; |
myDataHandleSize -= myShortenAmount; |
myPtr = *theSample + myOffsetLocation; |
*(U8 *)myPtr++ = (myButtonRecordLength & 0xFF); |
*(U8 *)myPtr++ = ((myButtonRecordLength >> 8) & 0xFF); |
} else { |
myMoveAmount = myDataHandleSize - gFlashParserData.m_tagEnd; |
BlockMove(*theSample + gFlashParserData.m_tagEnd, *theSample + myActionOffset, myMoveAmount); |
myShortenAmount = gFlashParserData.m_tagEnd - myActionOffset; |
myDataHandleSize -= myShortenAmount; |
// fixup previous offset to zero, because it is now last action |
myPtr = *theSample + myPrevOffset; |
*(U8 *)myPtr++ = (myButtonRecordLength & 0xFF); |
*(U8 *)myPtr++ = ((myButtonRecordLength >> 8) & 0xFF); |
} |
} else { |
myShortenAmount = sizeof(U16) + sizeof(U16) + sizeof(U8) + sizeof(U16) + myDataLength + sizeof(U8); |
myMoveAmount = myDataHandleSize - (myActionOffset + myShortenAmount); |
BlockMove(*theSample + myActionOffset + myShortenAmount, *theSample + myActionOffset, myMoveAmount); |
myDataHandleSize -= myShortenAmount; |
} |
// adjust sample length |
HUnlock(theSample); |
SetHandleSize(theSample, myDataHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
// fixup button taglength and data stream length |
SetNewHeaderLengthTagLength(-myShortenAmount, -myShortenAmount); |
} |
} else { |
if (theAction != NULL) { |
// insert new data |
myActionHandleSize = GetHandleSize((Handle)theAction); |
myMoveAmount = myDataHandleSize - myStartActionOffset; |
myIncreaseAmount = sizeof(U16) + sizeof(U16) + sizeof(U8) + sizeof(U16) + myActionHandleSize + sizeof(U8); |
myDataHandleSize += myIncreaseAmount; |
SetHandleSize(theSample, myDataHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
HLock((Handle)theAction); |
BlockMove(*theSample + myStartActionOffset, *theSample + myStartActionOffset + myIncreaseAmount, myMoveAmount); |
// patch in length of action data which is myOffset to next action |
myPtr = *theSample + myStartActionOffset; |
if (myActionCount) { |
*myPtr++ = (myIncreaseAmount & 0xFF); |
*myPtr++ = ((myIncreaseAmount >> 8) & 0xFF); |
} else { |
*(U16 *)myPtr = 0; |
myPtr += sizeof(U16); |
} |
// patch in condition |
*(U8 *)myPtr++ = (theCondition & 0xFF); |
*(U8 *)myPtr++ = ((theCondition >> 8) & 0xFF); |
// patch in wired action constant and length of action container |
*(U8 *)myPtr = sactionWiredActions; |
myPtr += sizeof(U8); |
*(U8 *)myPtr++ = (myActionHandleSize & 0xFF); |
*(U8 *)myPtr++ = ((myActionHandleSize >> 8) & 0xFF); |
// copy in new data |
BlockMove(*theAction, myPtr, myActionHandleSize); |
*(myPtr + myActionHandleSize) = 0; |
// patch in magic myOffset to start of actions at beginning of button data if needed |
if (myActionCount == 0) { |
myPtr = *theSample + myOffsetLocation; |
*(U8 *)myPtr++ = (myButtonRecordLength & 0xFF); |
*(U8 *)myPtr++ = ((myButtonRecordLength >> 8) & 0xFF); |
} |
HUnlock((Handle)theAction); |
HUnlock(theSample); |
// fixup button taglength and data stream length |
SetNewHeaderLengthTagLength(myIncreaseAmount, myIncreaseAmount); |
} |
} |
bail: |
return; |
} |
////////// |
// |
// AddFLAct_SetWiredActionsToButton |
// Step through the action container to add individual actions to the button data stream. |
// |
// This assumes that the actions are created in an editor for all actions for the button. |
// |
////////// |
static OSErr AddFLAct_SetWiredActionsToButton (Handle theSample, long theButtonID, QTAtomContainer theActions) |
{ |
short myIndex; |
QTAtomContainer myActionContainer; |
QTAtom myEventAtom = 0; |
QTAtomID myEventID; |
OSErr myErr; |
myErr = QTNewAtomContainer(&myActionContainer); |
if (myErr != noErr) |
goto bail; |
for (myIndex = 0; myIndex < (sizeof(gFlashConditions) / sizeof(long)); myIndex++) { |
myEventID = gFlashConditions[myIndex]; |
myEventAtom = QTFindChildByID(theActions, kParentAtomIsContainer, kQTEventType, myEventID, NULL); |
if (myEventAtom != 0) { |
myErr = AddFLAct_CopyChildren(theActions, myEventAtom, myActionContainer, kParentAtomIsContainer); |
if (myErr != noErr) |
goto bail; |
AddFLAct_SetWiredActionToButton(theSample, theButtonID, myEventID, myActionContainer); |
myErr = QTRemoveChildren(myActionContainer, kParentAtomIsContainer); |
if (myErr != noErr) |
goto bail; |
} else { |
AddFLAct_SetWiredActionToButton(theSample, theButtonID, myEventID, NULL); |
} |
} |
myErr = QTDisposeAtomContainer(myActionContainer); |
if (myErr != noErr) |
goto bail; |
bail: |
return(myErr); |
} |
////////// |
// |
// AddFLAct_SetFrameLoadedWiredActions |
// Add actions to frame data stream. |
// |
////////// |
static OSErr AddFLAct_SetFrameLoadedWiredActions (Handle theSample, long theFrameID, QTAtomContainer theActions) |
{ |
short myActionCount; |
U32 myOffset; |
U32 myEndOffset; |
U32 myStart; |
U32 myActionOffset = 0; |
U32 myActionDataOffset; |
long myActionHandleSize; |
long myDataHandleSize; |
long myNewHandleSize; |
long myShortenAmount; |
long myIncreaseAmount; |
long myMoveAmount; |
long myDifference = 0; |
long myFileDifference = 0; |
long myTagDifference; |
QTAtomContainer myNewContainer = NULL; |
QTAtom myEventAtom = 0; |
U8 myActionCode; |
U8 myNextActionCode; |
Ptr myPtr = NULL; |
OSErr myErr = noErr; |
gFlashParserData.m_theData = theSample; |
HLock(theSample); |
myDataHandleSize = GetHandleSize(theSample); |
GetOffsetForFrame(theFrameID, &myOffset, &myEndOffset); |
if (myOffset != 0) { |
gFlashParserData.m_fileBuf = (U8 *)*theSample; |
gFlashParserData.m_filePos = myOffset; |
// find any current flash doAction data |
while (gFlashParserData.m_filePos < myEndOffset) { |
U16 myCode; |
U32 myTagEnd; |
myStart = gFlashParserData.m_filePos; |
// get the current tag. |
myCode = GetTag(); |
// Get the tag ending position. |
myTagEnd = gFlashParserData.m_tagEnd; |
if (myCode == stagDoAction) { |
if (myActionOffset == 0) { |
myActionOffset = myStart; |
myActionDataOffset = gFlashParserData.m_filePos; |
} |
myActionCount = 0; |
// search for any previous wired actions |
do { |
myActionCount++; |
myActionCode = GetByte(); |
if (myActionCode == sactionWiredActions) { |
U32 myContainerLength = (U32)GetWord(); |
myMoveAmount = myDataHandleSize - (gFlashParserData.m_filePos + myContainerLength); |
if (theActions != NULL) { |
// replace |
myEventAtom = QTFindChildByID(theActions, kParentAtomIsContainer, kQTEventFrameLoaded, kIndexOne, NULL); |
if (myEventAtom == 0) |
goto bail; |
myErr = QTNewAtomContainer(&myNewContainer); |
if (myErr != noErr) |
goto bail; |
myErr = AddFLAct_CopyChildren(theActions, myEventAtom, myNewContainer, kParentAtomIsContainer); |
if (myErr != noErr) |
goto bail; |
myActionHandleSize = GetHandleSize(myNewContainer); |
if (myContainerLength != myActionHandleSize) { |
// need to create space |
if (myContainerLength > myActionHandleSize) { |
// compact space for new data |
myShortenAmount = myContainerLength - myActionHandleSize; |
myFileDifference = -myShortenAmount; |
myTagDifference = myFileDifference; |
BlockMove( *theSample + gFlashParserData.m_filePos + myContainerLength, |
*theSample + gFlashParserData.m_filePos + myContainerLength - myShortenAmount, |
myMoveAmount); |
HUnlock(theSample); |
myNewHandleSize = myDataHandleSize - myShortenAmount; |
SetHandleSize(theSample, myNewHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
} else { |
// expand space for new data |
myIncreaseAmount = myActionHandleSize - myContainerLength; |
myFileDifference = myIncreaseAmount; |
myTagDifference = myFileDifference; |
myNewHandleSize = myDataHandleSize + myIncreaseAmount; |
HUnlock(theSample); |
SetHandleSize(theSample, myNewHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
BlockMove(*theSample + gFlashParserData.m_filePos + myContainerLength, |
*theSample + gFlashParserData.m_filePos + myContainerLength + myIncreaseAmount, |
myMoveAmount); |
} |
} |
// copy in new data |
HLock ((Handle) myNewContainer); |
BlockMove (*myNewContainer, *theSample + gFlashParserData.m_filePos, myActionHandleSize); |
HUnlock ((Handle) myNewContainer); |
// patch in action length |
myPtr = *theSample + gFlashParserData.m_filePos - sizeof(U16); |
myPtr[0] = (myActionHandleSize & 0xFF); |
myPtr[1] = ((myActionHandleSize >> 8) & 0xFF); |
} else { |
// remove |
myNextActionCode = *(U8 *)(*theSample + gFlashParserData.m_filePos + myContainerLength); |
if ((myActionCount == 1) && (myNextActionCode == 0)) { |
// need to remove whole tag |
myMoveAmount = myDataHandleSize - myTagEnd; |
myFileDifference = myActionOffset - myTagEnd; |
myTagDifference = 0; |
myNewHandleSize = myDataHandleSize - (myTagEnd - myActionOffset); |
BlockMove(*theSample + myTagEnd, *theSample + myActionOffset, myMoveAmount); |
} else { |
// compact space to remove unneeded data |
myFileDifference = -(myContainerLength + sizeof(U8) + sizeof(U16)); // U32 |
myTagDifference = myFileDifference; |
myNewHandleSize = myDataHandleSize + myFileDifference; |
BlockMove( *theSample + gFlashParserData.m_filePos + myContainerLength, |
*theSample + gFlashParserData.m_filePos - (sizeof(U8) + sizeof(U16)), |
myMoveAmount); // U32 |
} |
SetHandleSize (theSample, myNewHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
} |
if (myFileDifference) { |
// fixup frame taglength and data stream length |
SetNewHeaderLengthTagLength (myFileDifference, myTagDifference); |
} |
goto bail; |
} else { |
if ((myActionCode & 0x80) != 0) { |
U32 myContainerLength = (U32)GetWord(); |
gFlashParserData.m_filePos += myContainerLength - 1; |
} |
} |
} |
while (myActionCode); |
} |
// increment past the tag. |
gFlashParserData.m_filePos = myTagEnd; |
} |
// not found - therefore insert |
if (theActions != NULL) { |
// do we really have something to insert? |
myEventAtom = QTFindChildByID(theActions, kParentAtomIsContainer, kQTEventFrameLoaded, kIndexOne, NULL); |
if (myEventAtom == 0) |
goto bail; |
myErr = QTNewAtomContainer(&myNewContainer); |
if (myErr != noErr) |
goto bail; |
myErr = AddFLAct_CopyChildren(theActions, myEventAtom, myNewContainer, kParentAtomIsContainer); |
if (myErr != noErr) |
goto bail; |
myActionHandleSize = GetHandleSize(myNewContainer); |
if (myActionOffset) { |
// then we already have actions - just insert at front |
// expand space for new data |
gFlashParserData.m_tagStart = myActionOffset; |
myDifference = sizeof(U8) + sizeof(U16) + myActionHandleSize; // U32 |
myNewHandleSize = myDataHandleSize + myDifference; |
myMoveAmount = myDataHandleSize - myActionDataOffset; // myActionOffset; |
HUnlock(theSample); |
SetHandleSize(theSample, myNewHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
myPtr = *theSample + myActionDataOffset; // myActionOffset; |
BlockMove(myPtr, myPtr + sizeof(U8) + sizeof(U16) + myActionHandleSize, myMoveAmount); |
// patch in our action code |
*(U8 *)myPtr = sactionWiredActions; |
myPtr += sizeof(U8); |
// patch in data length |
myPtr[0] = (myActionHandleSize & 0xFF); |
myPtr[1] = ((myActionHandleSize >> 8) & 0xFF); |
// copy in new data |
myPtr += sizeof(U16); |
HLock((Handle)myNewContainer); |
BlockMove(*myNewContainer, myPtr, myActionHandleSize); |
HUnlock((Handle)myNewContainer); |
myFileDifference = myDifference; |
myTagDifference = myDifference; |
} else { |
// no other actions - create new doAction event |
U16 myNewCode = stagDoAction << 6; |
gFlashParserData.m_tagStart = myEndOffset; |
// expand space for new data |
myDifference = sizeof(U16) + sizeof(U8) + sizeof(U16) + myActionHandleSize + sizeof(U8); |
myNewHandleSize = myDataHandleSize + myDifference; |
myMoveAmount = myDataHandleSize - myEndOffset; |
HUnlock(theSample); |
SetHandleSize(theSample, myNewHandleSize); |
myErr = MemError(); |
if (myErr != noErr) |
goto bail; |
HLock(theSample); |
myPtr = *theSample + myEndOffset; |
if (myMoveAmount != 0) |
BlockMove(myPtr, myPtr + myDifference, myMoveAmount); |
// patch in doAction code |
*(U8 *)myPtr = (myNewCode & 0xFF); |
myPtr += sizeof(U8); |
*(U8 *)myPtr = ((myNewCode >> 8) & 0xFF); |
myPtr += sizeof(U8); |
// patch in wired action code |
*(U8 *)myPtr = sactionWiredActions; |
myPtr += sizeof(U8); |
// patch in data length |
myPtr[0] = (myActionHandleSize & 0xFF); |
myPtr[1] = ((myActionHandleSize >> 8) & 0xFF); |
// copy in new data |
myPtr += sizeof(U16); |
HLock((Handle) myNewContainer); |
BlockMove(*myNewContainer, myPtr, myActionHandleSize); |
HUnlock((Handle) myNewContainer); |
// patch in end marker |
myPtr += myActionHandleSize; |
*(U8 *)myPtr = 0; // action terminator |
myFileDifference = myDifference; |
myTagDifference = myDifference - sizeof(U16); |
} |
HUnlock(theSample); |
// fixup frame taglength and data stream length |
SetNewHeaderLengthTagLength(myFileDifference, myTagDifference); |
} |
// else // nothing to do! |
} |
bail: |
if (myNewContainer != NULL) |
(void)QTDisposeAtomContainer(myNewContainer); |
return(myErr); |
} |
/////////// |
// |
// AddFLAct_AddWiredActionsToFlashMovie |
// Add some wired actions to the specified Flash movie. |
// |
////////// |
static void AddFLAct_AddWiredActionsToFlashMovie (FSSpec *theFSSpec) |
{ |
short myResID = 0; |
short myResRefNum; |
Movie myMovie = NULL; |
Track myTrack = NULL; |
Media myMedia = NULL; |
TimeValue myTrackOffset; |
TimeValue myMediaTime; |
TimeValue mySampleDuration; |
TimeValue mySelectionDuration; |
TimeValue myNewMediaTime; |
FlashDescriptionHandle myFlashDesc = NULL; |
Handle mySample = NULL; |
short mySampleFlags; |
Fixed myTrackEditRate; |
QTAtomContainer myActions = NULL; |
long myButtonID = 0L; |
OSErr myErr = noErr; |
////////// |
// |
// open the movie file and get the first Flash track from the movie |
// |
////////// |
// open the movie file for reading and writing |
myErr = OpenMovieFile(theFSSpec, &myResRefNum, fsRdWrPerm); |
if (myErr != noErr) |
goto bail; |
myErr = NewMovieFromFile(&myMovie, myResRefNum, &myResID, NULL, newMovieActive, NULL); |
if (myErr != noErr) |
goto bail; |
// find the first Flash track in the movie; |
myTrack = GetMovieIndTrackType(myMovie, kIndexOne, FlashMediaType, movieTrackMediaType); |
if (myTrack == NULL) |
goto bail; |
////////// |
// |
// get first media sample in the Flash track |
// |
////////// |
myMedia = GetTrackMedia(myTrack); |
if (myMedia == NULL) |
goto bail; |
myTrackOffset = GetTrackOffset(myTrack); |
myMediaTime = TrackTimeToMediaTime(myTrackOffset, myTrack); |
// allocate some storage to hold the sample description for the Flash track |
myFlashDesc = (FlashDescriptionHandle)NewHandle(4); |
if (myFlashDesc == NULL) |
goto bail; |
mySample = NewHandle(0); |
if (mySample == NULL) |
goto bail; |
myErr = GetMediaSample(myMedia, mySample, 0, NULL, myMediaTime, NULL, &mySampleDuration, (SampleDescriptionHandle)myFlashDesc, NULL, 1, NULL, &mySampleFlags); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add frame-loaded actions |
// |
////////// |
// create an action container for frame-loaded actions |
myErr = AddFLAct_CreateFrameLoadedActionContainer(&myActions); |
if (myErr != noErr) |
goto bail; |
// add frame-loaded actions to sample |
myErr = AddFLAct_SetFrameLoadedWiredActions(mySample, kIndexZero, myActions); |
if (myErr != noErr) |
goto bail; |
myErr = QTDisposeAtomContainer(myActions); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// add button actions |
// |
////////// |
// find the first button |
myErr = LocateFirstButton(mySample, &myButtonID); |
if ((myErr != noErr) || (myButtonID == 0)) |
goto bail; |
// create an action container for button actions |
myErr = AddFLAct_CreateButtonActionContainer(&myActions); |
if (myErr != noErr) |
goto bail; |
// add button actions to sample |
myErr = AddFLAct_SetWiredActionsToButton(mySample, myButtonID, myActions); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// replace sample in media |
// |
////////// |
myTrackEditRate = GetTrackEditRate(myTrack, myTrackOffset); |
if (GetMoviesError() != noErr) |
goto bail; |
GetTrackNextInterestingTime(myTrack, nextTimeMediaSample | nextTimeEdgeOK, myTrackOffset, fixed1, NULL, &mySelectionDuration); |
if (GetMoviesError() != noErr) |
goto bail; |
myErr = DeleteTrackSegment(myTrack, myTrackOffset, mySelectionDuration); |
if (myErr != noErr) |
goto bail; |
myErr = BeginMediaEdits(myMedia); |
if (myErr != noErr) |
goto bail; |
myErr = AddMediaSample( myMedia, |
mySample, |
0, |
GetHandleSize(mySample), |
mySampleDuration, |
(SampleDescriptionHandle)myFlashDesc, |
1, |
mySampleFlags, |
&myNewMediaTime); |
if (myErr != noErr) |
goto bail; |
myErr = EndMediaEdits(myMedia); |
if (myErr != noErr) |
goto bail; |
// add the media to the track |
myErr = InsertMediaIntoTrack(myTrack, myTrackOffset, myNewMediaTime, mySelectionDuration, myTrackEditRate); |
if (myErr != noErr) |
goto bail; |
////////// |
// |
// update the movie resource |
// |
////////// |
myErr = UpdateMovieResource(myMovie, myResRefNum, myResID, NULL); |
bail: |
// close the movie file |
if (myResRefNum != -1) |
CloseMovieFile(myResRefNum); |
if (myActions != NULL) |
(void)QTDisposeAtomContainer(myActions); |
if (mySample != NULL) |
DisposeHandle(mySample); |
if (myFlashDesc != NULL) |
DisposeHandle((Handle)myFlashDesc); |
if (myMovie != NULL) |
DisposeMovie(myMovie); |
} |
/////////// |
// |
// AddFLAct_CopyAtomAndChildren |
// Copy an atom and all its the children from one atom container to another. |
// |
////////// |
static OSErr AddFLAct_CopyAtomAndChildren (QTAtomContainer theSrcContainer, QTAtom theSrcAtom, QTAtomContainer theDstContainer, QTAtom theDstAtom) |
{ |
QTAtomContainer myCopyAtomContainer = NULL; |
OSErr myErr = noErr; |
myErr = QTCopyAtom(theSrcContainer, theSrcAtom, &myCopyAtomContainer); |
if (myErr != noErr) |
goto bail; |
myErr = QTInsertChildren(theDstContainer, theDstAtom, myCopyAtomContainer); |
if (myErr != noErr) |
goto bail; |
myErr = QTDisposeAtomContainer(myCopyAtomContainer); |
bail: |
return(myErr); |
} |
/////////// |
// |
// AddFLAct_CopyChildren |
// Copy the children in one atom container to another. |
// |
////////// |
static OSErr AddFLAct_CopyChildren (QTAtomContainer theSrcContainer, QTAtom theSrcAtom, QTAtomContainer theDstContainer, QTAtom theDstAtom) |
{ |
QTAtom myCurrentAtom = 0; |
QTAtom myNextAtom = 0; |
OSErr myErr = noErr; |
do { |
myErr = QTNextChildAnyType(theSrcContainer, theSrcAtom, myCurrentAtom, &myNextAtom); |
if (myErr != noErr) |
goto bail; |
if (myNextAtom != 0) { |
myErr = AddFLAct_CopyAtomAndChildren(theSrcContainer, myNextAtom, theDstContainer, theDstAtom); |
if (myErr != noErr) |
goto bail; |
} |
myCurrentAtom = myNextAtom; |
} while (myNextAtom != 0); |
bail: |
return(myErr); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-02-25