smlparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:879k
- }
- HX_RELEASE(pFact);
- }
- }
- const char* CSmilParser::getEnumAttrString(SMIL2Attribute eAttr, BYTE ucVal)
- {
- const char* pRet = NULL;
- struct EnumAttrTable* pEntry = (struct EnumAttrTable*) &g_EnumAttrTable[0];
- while (pEntry && pEntry->m_eAttr != NumSMIL2Attributes)
- {
- if (pEntry->m_eAttr == eAttr &&
- pEntry->m_ucEnum == ucVal)
- {
- pRet = pEntry->m_pszStr;
- break;
- }
- pEntry++;
- }
- return pRet;
- }
- BOOL CSmilParser::isAttributeAnimated(const char* pszElementID,
- UINT32 ulAttrName)
- {
- BOOL bRet = FALSE;
- #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
- if (m_pAnimateElementList)
- {
- LISTPOSITION pos = m_pAnimateElementList->GetHeadPosition();
- while (pos)
- {
- CSmilAnimateElement* pAnim =
- (CSmilAnimateElement*) m_pAnimateElementList->GetNext(pos);
- if (pAnim &&
- ((UINT32) pAnim->m_ucAttributeName) == ulAttrName &&
- pAnim->m_pTargetElementID &&
- *pAnim->m_pTargetElementID == pszElementID)
- {
- bRet = TRUE;
- break;
- }
- }
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
- return bRet;
- }
- SMIL2Element CSmilParser::getSMIL2Element(const char* pszStr)
- {
- SMIL2Element eRet = NumSMIL2Elements;
- if (pszStr && m_pElementMap)
- {
- void* pVoid = NULL;
- if (m_pElementMap->Lookup(pszStr, pVoid))
- {
- eRet = (SMIL2Element) (UINT32) pVoid;
- }
- }
- return eRet;
- }
- SMIL2Attribute CSmilParser::getSMIL2Attribute(const char* pszStr)
- {
- SMIL2Attribute eRet = NumSMIL2Attributes;
- if (pszStr && m_pAttributeMap)
- {
- void* pVoid = NULL;
- if (m_pAttributeMap->Lookup(pszStr, pVoid))
- {
- eRet = (SMIL2Attribute) (UINT32) pVoid;
- }
- }
- return eRet;
- }
- void CSmilParser::checkForExternalEvents()
- {
- // Get the <body> node
- SMILNode* pBody = findFirstNode(SMILBody);
- if (pBody)
- {
- // Check recursively for custom events
- checkNodeForExternalEvents(pBody);
- }
- }
- BOOL CSmilParser::anyExternalEvents(const char* pszID)
- {
- BOOL bRet = FALSE;
- if (m_pExternalEventList)
- {
- LISTPOSITION pos = m_pExternalEventList->GetHeadPosition();
- while (pos)
- {
- ExternalEventInfo* pInfo =
- (ExternalEventInfo*) m_pExternalEventList->GetNext(pos);
- if (pInfo &&
- pInfo->m_EventBaseID == pszID)
- {
- bRet = TRUE;
- break;
- }
- }
- }
- return bRet;
- }
- ExternalEventInfo* CSmilParser::getFirstExternalEvent(const char* pszID)
- {
- ExternalEventInfo* pRet = NULL;
- if (m_pExternalEventList)
- {
- // Initialize the iterator to the first external
- // event in the list
- m_pExternalEventListPos = m_pExternalEventList->GetHeadPosition();
- // Now just call getNextExternalEvent()
- pRet = getNextExternalEvent(pszID);
- }
- return pRet;
- }
- ExternalEventInfo* CSmilParser::getNextExternalEvent(const char* pszID)
- {
- ExternalEventInfo* pRet = NULL;
- if (m_pExternalEventList)
- {
- while (m_pExternalEventListPos)
- {
- ExternalEventInfo* pInfo =
- (ExternalEventInfo*) m_pExternalEventList->GetNext(m_pExternalEventListPos);
- if (pInfo &&
- pInfo->m_EventBaseID == pszID)
- {
- pRet = pInfo;
- break;
- }
- }
- }
- return pRet;
- }
- void CSmilParser::checkForEventHandlers()
- {
- if (m_pElementsWithHandlerList)
- {
- LISTPOSITION pos = m_pElementsWithHandlerList->GetHeadPosition();
- while (pos)
- {
- CSmilSource* pSrc =
- (CSmilSource*) m_pElementsWithHandlerList->GetNext(pos);
- if (pSrc && pSrc->m_pNode && pSrc->m_HandlerID.GetLength() > 0)
- {
- // Look up the element with this handler id
- CSmilElement* pEl =
- findElement((const char*) pSrc->m_HandlerID);
- if (pEl && isMediaObject(pEl->m_pNode))
- {
- // Cast to a source
- CSmilSource* pHandlerSrc = (CSmilSource*) pEl;
- // Set the "handler-for" member in this element
- pHandlerSrc->m_HandlerFor = pSrc->m_pNode->m_id;
- }
- }
- }
- }
- }
- AccessErrorBehavior CSmilParser::getAccessErrorBehavior(SMILNode* pNode)
- {
- // This is default
- AccessErrorBehavior eRet = AccessErrorBehaviorInherit;
- if (pNode)
- {
- // Now init the value to be AccessErrorBehaviorInherit
- // Get the value from the CSmilElement if there is one
- if (pNode->m_pElement)
- {
- eRet = pNode->m_pElement->m_eAccessErrorBehavior;
- }
- // If this value is inherit, then look to the parent
- if (eRet == AccessErrorBehaviorInherit)
- {
- if (pNode->m_pParent)
- {
- eRet = getAccessErrorBehavior(pNode->m_pParent);
- }
- else
- {
- eRet = AccessErrorBehaviorContinue;
- }
- }
- }
- return eRet;
- }
- #ifdef XXXMEH_EXTERNAL_MEDIA_MARKER_HACK
- HX_RESULT CSmilParser::getExternalMarkerFileTime(const char* pszMarker,
- const char* pszSMILFileURL,
- const char* pszSrcURL,
- REF(UINT32) rulTime)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszMarker)
- {
- CHXString cMarker;
- CHXString cExtFile;
- BOOL bExternal = FALSE;
- retVal = parseMarkerURI(pszMarker, cMarker, bExternal, cExtFile);
- if (SUCCEEDED(retVal))
- {
- if (bExternal)
- {
- CHXString cExtFileName;
- retVal = constructExternalMarkerFileName(cExtFile,
- pszSMILFileURL,
- pszSrcURL,
- cExtFileName);
- if (SUCCEEDED(retVal))
- {
- // Strip the "file://" off the front
- const char* pszExtFileName = (const char*) cExtFileName;
- if (!strncmp(pszExtFileName, "file://", 7))
- {
- pszExtFileName += 7;
- }
- // Open the file
- FILE* fp = fopen(pszExtFileName, "r");
- if (fp)
- {
- char szLine[128]; /* Flawfinder: ignore */
- fgets(szLine, 128, fp);
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (!strcmp(szLine, "// The format of this file is solely for SMIL 2.0 Interop testing."))
- {
- fgets(szLine, 128, fp);
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (!strcmp(szLine, "// It must not be supported in publicly-released software."))
- {
- // Now loop through the lines
- while (!feof(fp))
- {
- fgets(szLine, 128, fp);
- if (strlen(szLine) > 0)
- {
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (szLine[strlen(szLine) - 1] == 'r' ||
- szLine[strlen(szLine) - 1] == 'n')
- {
- szLine[strlen(szLine) - 1] = ' ';
- }
- if (strlen(szLine) > 0)
- {
- // Parse the line
- char* pszToken = strtok(szLine, " t");
- if (pszToken)
- {
- if (!strcmp(pszToken, (const char*) cMarker))
- {
- pszToken = strtok(NULL, " t");
- if (pszToken)
- {
- HX_RESULT rv = parseClockValue(pszToken, rulTime);
- if (SUCCEEDED(rv))
- {
- retVal = HXR_OK;
- break;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- fclose(fp);
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::constructExternalMarkerFileName(const char* pszMarkerFile,
- const char* pszSMILFileURL,
- const char* pszSrcURL,
- REF(CHXString) rcExtMarkerFileName)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszMarkerFile && pszSMILFileURL && pszSrcURL)
- {
- // Get the URL prefix, root, and fragment
- CHXString cPrefix;
- CHXString cURLRoot;
- char* pURLFragment = NULL;
- CHXURL::GeneratePrefixRootFragment(pszSMILFileURL,
- cPrefix,
- cURLRoot,
- pURLFragment);
- // Get the full URL for the src
- CHXString cFullSrcURL;
- CHXURL urlObj(pszSrcURL);
- CHXHeader* pHeader = urlObj.GetProperties();
- if (pHeader)
- {
- IHXBuffer* pBuffer = NULL;
- HX_RESULT rc = pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer);
- if (SUCCEEDED(rc))
- {
- // fully qualified URL
- cFullSrcURL = pszSrcURL;
- }
- else
- {
- // relative URL
- // if it starts with '/', make it relative to the root of
- // the URL prefix
- if(*pszSrcURL == '/')
- {
- cFullSrcURL = cURLRoot + pszSrcURL;
- }
- else
- {
- cFullSrcURL = cPrefix + pszSrcURL;
- }
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeader);
- }
- if (cFullSrcURL.GetLength() > 0)
- {
- HX_VECTOR_DELETE(pURLFragment);
- CHXURL::GeneratePrefixRootFragment(cFullSrcURL,
- cPrefix,
- cURLRoot,
- pURLFragment);
- // Now we need to create the external marker file name
- CHXString cFullMarkerURL;
- CHXURL urlObj2(pszMarkerFile);
- CHXHeader* pHeader2 = urlObj2.GetProperties();
- if (pHeader2)
- {
- IHXBuffer* pBuffer = NULL;
- HX_RESULT rc = pHeader2->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer);
- if (SUCCEEDED(rc))
- {
- // fully qualified URL
- cFullMarkerURL = pszMarkerFile;
- }
- else
- {
- // relative URL
- // if it starts with '/', make it relative to the root of
- // the URL prefix
- if(*pszMarkerFile == '/')
- {
- cFullMarkerURL = cURLRoot + pszMarkerFile;
- }
- else
- {
- cFullMarkerURL = cPrefix + pszMarkerFile;
- }
- }
- HX_RELEASE(pBuffer);
- HX_RELEASE(pHeader);
- }
- rcExtMarkerFileName = cFullMarkerURL;
- }
- HX_VECTOR_DELETE(pURLFragment);
- }
- else
- {
- retVal = HXR_OK;
- }
- return retVal;
- }
- #endif // XXXMEH_EXTERNAL_MEDIA_MARKER_HACK
- HX_RESULT CSmilParser::parseMarkerURI(const char* pszStr,
- REF(CHXString) rcMarker,
- REF(BOOL) rbExternal,
- REF(CHXString) rcExternalFileName)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- // Look for a '#'
- char* pHash = (char *)strchr(pszStr, '#');
- if (pHash)
- {
- // We DO have a hash. Is there a file
- // name in front of it?
- if (pHash > pszStr)
- {
- // We DO have a hash, so parse out the
- // external file name AND the marker name
- *pHash = ' ';
- rbExternal = TRUE;
- rcExternalFileName = pszStr;
- rcMarker = (const char*) pHash + 1;
- }
- else
- {
- // No file name in front of hash, so
- // it's still an internal marker
- rbExternal = FALSE;
- rcMarker = (const char*) pHash + 1;
- }
- }
- else
- {
- // No '#', so we know it's NOT an external marker
- rbExternal = FALSE;
- // So the marker is just the entire string
- rcMarker = pszStr;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::parseHandlerForID(const char* pszStr,
- REF(CHXString) rcHandlerID)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszStr)
- {
- const char* pPnd = strchr(pszStr, '#');
- if (pPnd)
- {
- rcHandlerID = pPnd + 1;
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::parseAccessErrorBehavior(const char* pszStr,
- REF(AccessErrorBehavior) reErr)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- if (!strcmp(pszStr, "inherit"))
- {
- reErr = AccessErrorBehaviorInherit;
- }
- else if (!strcmp(pszStr, "continue"))
- {
- reErr = AccessErrorBehaviorContinue;
- }
- else if (!strcmp(pszStr, "stop"))
- {
- reErr = AccessErrorBehaviorStop;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- #if defined(XXXMEH_SPLINE_ANIMATION)
- HX_RESULT CSmilParser::parseKeyTimes(const char* pszVal, CSmilAnimateElement* pAnim)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszVal && pAnim)
- {
- // Allocate some temporary memory to hold
- // a copy of the string
- char* pTmp = new char [strlen(pszVal) + 1];
- if (pTmp)
- {
- // Make a copy of the string, because
- // strtok() is destructive
- strcpy(pTmp, pszVal); /* Flawfinder: ignore */
- // First run through and count the number of tokens
- UINT32 ulNum = 0;
- const char* pszSep = " ;trn";
- char* pszToken = strtok(pTmp, pszSep);
- while (pszToken)
- {
- // Increment the number of tokens
- ++ulNum;
- // Get the next token
- pszToken = strtok(NULL, pszSep);
- }
- // Recopy the string
- strcpy(pTmp, pszVal); /* Flawfinder: ignore */
- // Set the number of keyTimes
- pAnim->m_ulNumKeyTimes = ulNum;
- // Allocate space for the keyTimes
- HX_VECTOR_DELETE(pAnim->m_pdKeyTime);
- pAnim->m_pdKeyTime = new double [pAnim->m_ulNumKeyTimes];
- if (pAnim->m_pdKeyTime)
- {
- // Parse the string using strtok()
- ulNum = 0;
- pszToken = strtok(pTmp, pszSep);
- while (pszToken && SUCCEEDED(retVal))
- {
- // Parse the current token
- double dTmp = 0.0;
- retVal = HXParseDouble(pszToken, dTmp);
- if (SUCCEEDED(retVal))
- {
- // SPEC: Each time value in the keyTimes list is specified
- // as a floating point value between 0 and 1 (inclusive),
- // representing a proportional offset into the simple
- // duration of the animation element.
- if (dTmp >= 0.0 && dTmp <= 1.0)
- {
- // Set the value
- pAnim->m_pdKeyTime[ulNum++] = dTmp;
- // Get the next token
- pszToken = strtok(NULL, pszSep);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- HX_VECTOR_DELETE(pTmp);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::parseKeySplines(const char* pszVal, CSmilAnimateElement* pAnim)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszVal && pAnim)
- {
- // Allocate some temporary memory to hold
- // a copy of the string
- char* pTmp = new char [strlen(pszVal) + 1];
- if (pTmp)
- {
- // Make a copy of the string, because
- // strtok() is destructive
- strcpy(pTmp, pszVal); /* Flawfinder: ignore */
- // First run through and count the number of keySplines
- UINT32 ulNum = 0;
- const char* pszSep = ";";
- char* pszToken = strtok(pTmp, pszSep);
- while (pszToken)
- {
- // Increment the number of tokens
- ++ulNum;
- // Get the next token
- pszToken = strtok(NULL, pszSep);
- }
- // Recopy the string
- strcpy(pTmp, pszVal); /* Flawfinder: ignore */
- // Set the number of keyTimes
- pAnim->m_ulNumKeySplines = ulNum;
- // Allocate space for the keyTimes
- HX_VECTOR_DELETE(pAnim->m_pKeySpline);
- pAnim->m_pKeySpline = new KeySpline [pAnim->m_ulNumKeySplines];
- if (pAnim->m_pKeySpline)
- {
- // Null out the array
- UINT32 i = 0;
- for (i = 0; i < pAnim->m_ulNumKeySplines; i++)
- {
- pAnim->m_pKeySpline[i].x1 = 0.0;
- pAnim->m_pKeySpline[i].y1 = 0.0;
- pAnim->m_pKeySpline[i].x2 = 0.0;
- pAnim->m_pKeySpline[i].y2 = 0.0;
- }
- // Allocate a buffer for holding the char*'s
- char** ppTok = new char * [pAnim->m_ulNumKeySplines]; /* Flawfinder: ignore */
- if (ppTok)
- {
- // Null out the array
- memset(ppTok, 0, pAnim->m_ulNumKeySplines * sizeof(char*));
- // Parse the string using strtok(). We simply
- // run through and save the pointers to the
- // keySplines so that we can parse them separately
- // in a separate loop. This is due to restrictions
- // of using strtok().
- ulNum = 0;
- pszToken = strtok(pTmp, pszSep);
- while (pszToken)
- {
- ppTok[ulNum++] = pszToken;
- // Get the next keySpline
- pszToken = strtok(NULL, pszSep);
- }
- // Now we can individually parse each keySpline
- for (UINT32 i = 0; i < pAnim->m_ulNumKeySplines && SUCCEEDED(retVal); i++)
- {
- if (ppTok[i])
- {
- char* pszKS = ppTok[i];
- const char* pszKSSep = " ,trn";
- char* pszKSToken = strtok(pszKS, pszKSSep);
- for (UINT32 j = 0; j < 4 && SUCCEEDED(retVal); j++)
- {
- if (pszKSToken)
- {
- // Parse the current token
- double dTmp = 0.0;
- retVal = HXParseDouble(pszKSToken, dTmp);
- if (SUCCEEDED(retVal))
- {
- // SPEC: The [keySplines] values must
- // all be in the range 0 to 1.
- if (dTmp >= 0.0 && dTmp <= 1.0)
- {
- // Set the value
- switch (j)
- {
- case 0: pAnim->m_pKeySpline[i].x1 = dTmp; break;
- case 1: pAnim->m_pKeySpline[i].y1 = dTmp; break;
- case 2: pAnim->m_pKeySpline[i].x2 = dTmp; break;
- case 3: pAnim->m_pKeySpline[i].y2 = dTmp; break;
- }
- // Get the next token
- pszKSToken = strtok(NULL, pszKSSep);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- HX_VECTOR_DELETE(ppTok);
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- HX_VECTOR_DELETE(pTmp);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT CSmilParser::parseSVGPath(const char* pszVal, CSmilAnimateElement* pAnim)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszVal && pAnim)
- {
- // XXXMEH - first we make a more restrictive parser that
- // requires whitespace or commas in between all tokens.
- // We will need to go back later and make a looser parser
- // that complies with the BNF.
- //
- // Allocate some memory to copy the string
- char* pTmp = new char [strlen(pszVal) + 1];
- if (pTmp)
- {
- // Copy the string, since strtok() is destructive
- strcpy(pTmp, pszVal); /* Flawfinder: ignore */
- // This array will hold PathCmd*'s and we
- // will copy them into the final array at the end
- CHXPtrArray cTmpArr;
- UINT32 ulNumCmd = 0;
- // This array will hold the list of coordinates
- // until we know how many there are
- UINT32 ulNumTmp = 0;
- UINT32 ulNumTmpAlloc = 0;
- double* pdTmp = NULL;
- // Loop through the tokens
- const char* pszSep = " ,trn";
- char* pTok = strtok(pTmp, pszSep);
- PathCmd* pCurCmd = NULL;
- while (pTok && SUCCEEDED(retVal))
- {
- // Is this token a command?
- BOOL bIsCmdType = FALSE;
- BOOL bRelative = FALSE;
- PathCmdType eType = PathCmdTypeMoveTo;
- if (strlen(pTok) == 1)
- {
- char c = *pTok;
- if (isalpha(c))
- {
- if (islower(c))
- {
- bRelative = TRUE;
- c = toupper(c);
- }
- bIsCmdType = TRUE;
- switch(c)
- {
- case 'M': eType = PathCmdTypeMoveTo; break;
- case 'Z': eType = PathCmdTypeClosePath; break;
- case 'L': eType = PathCmdTypeLineTo; break;
- case 'H': eType = PathCmdTypeHorzLineTo; break;
- case 'V': eType = PathCmdTypeVertLineTo; break;
- case 'C': eType = PathCmdTypeCubicBezierCurveTo; break;
- default: bIsCmdType = FALSE;
- }
- }
- }
- // We now know whether or not this token
- // is a command or not. It either has to
- // be a command or a coordinate. If it's a command
- // and we already have a current PathCmd, then
- // add the current one to the list and create
- // another one. If it's not a command (and thus
- // is a coordinate), then we have to decide where
- // it goes in the current PathCmd.
- if (bIsCmdType)
- {
- // This is a command type. Do
- // we already have a current PathCmd?
- if (pCurCmd)
- {
- // Check the number of coordinates against
- // the type. MoveTo and LineTo commands must
- // have an even number of coordinates. ClosePath
- // commands should have zero coordinates.
- // BezierCurveTo should have a multiple of 6
- // coordinates.
- BOOL bLegalNumber = TRUE;
- switch (pCurCmd->m_eType)
- {
- case PathCmdTypeMoveTo:
- case PathCmdTypeLineTo:
- {
- if (!ulNumTmp || (ulNumTmp%2))
- {
- bLegalNumber = FALSE;
- }
- }
- break;
- case PathCmdTypeHorzLineTo:
- case PathCmdTypeVertLineTo:
- {
- if (!ulNumTmp)
- {
- bLegalNumber = FALSE;
- }
- }
- break;
- case PathCmdTypeClosePath:
- {
- if (ulNumTmp)
- {
- bLegalNumber = FALSE;
- }
- }
- break;
- case PathCmdTypeCubicBezierCurveTo:
- {
- if (!ulNumTmp || (ulNumTmp%6))
- {
- bLegalNumber = FALSE;
- }
- }
- break;
- }
- // Do we have a legal number of coordinates?
- if (bLegalNumber)
- {
- // Set the number of coordinates
- pCurCmd->m_ulNumCoords = ulNumTmp;
- // Alloc space
- if (ulNumTmp)
- {
- pCurCmd->m_pdCoord = new double [ulNumTmp];
- if (pCurCmd->m_pdCoord)
- {
- // Copy the values and zero out the
- // tmp array
- for (UINT32 i = 0; i < ulNumTmp; i++)
- {
- pCurCmd->m_pdCoord[i] = pdTmp[i];
- pdTmp[i] = 0.0;
- }
- // Reset the number of coordinates
- ulNumTmp = 0;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // We already have a current PathCmd,
- // so add the current one to the array
- cTmpArr.SetAt(ulNumCmd++, (void*) pCurCmd);
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Create a new PathCmd
- pCurCmd = new PathCmd();
- if (pCurCmd)
- {
- pCurCmd->m_eType = eType;
- pCurCmd->m_bRelative = bRelative;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- else
- {
- // This must be a coordinate, so parse it as
- // a coordinate
- double dTmp = 0;
- retVal = HXParseDouble(pTok, dTmp);
- if (SUCCEEDED(retVal))
- {
- // We successfully parsed a coordinate, so check
- // and see if the array has enough space to add
- // one more element
- if (ulNumTmp >= ulNumTmpAlloc)
- {
- // Not enough space, so we need to alloc
- // some more space. Double the size of
- // the array
- UINT32 ulNewNumTmpAlloc = ulNumTmpAlloc << 1;
- if (!ulNewNumTmpAlloc)
- {
- ulNewNumTmpAlloc = 8;
- }
- double* pCpy = new double [ulNewNumTmpAlloc];
- if (pCpy)
- {
- // Copy the old values
- UINT32 i = 0;
- for (i = 0; i < ulNumTmpAlloc; i++)
- {
- pCpy[i] = pdTmp[i];
- }
- // NULL out the rest of the array
- for (i = ulNumTmpAlloc; i < ulNewNumTmpAlloc; i++)
- {
- pCpy[i] = 0.0;
- }
- // Delete the old array
- HX_VECTOR_DELETE(pdTmp);
- // Assign it to the new array
- pdTmp = pCpy;
- // Update the number allocated
- ulNumTmpAlloc = ulNewNumTmpAlloc;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- if (SUCCEEDED(retVal))
- {
- pdTmp[ulNumTmp++] = dTmp;
- }
- }
- }
- // Get the next token
- pTok = strtok(NULL, pszSep);
- }
- // Copy the last PathCmd* to the list
- if (pCurCmd)
- {
- // Set the number of coordinates
- pCurCmd->m_ulNumCoords = ulNumTmp;
- // Alloc space
- if (ulNumTmp)
- {
- pCurCmd->m_pdCoord = new double [ulNumTmp];
- if (pCurCmd)
- {
- // Copy the values and zero out the
- // tmp array
- for (UINT32 i = 0; i < ulNumTmp; i++)
- {
- pCurCmd->m_pdCoord[i] = pdTmp[i];
- pdTmp[i] = 0.0;
- }
- // Reset the number of coordinates
- ulNumTmp = 0;
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- if (SUCCEEDED(retVal))
- {
- // We already have a current PathCmd,
- // so add the current one to the array
- cTmpArr.SetAt(ulNumCmd++, (void*) pCurCmd);
- }
- }
- // Now we can delete the temporary array of coordinates
- HX_VECTOR_DELETE(pdTmp);
- // Copy from the temporary list to the CSmilAnimateElement
- if (SUCCEEDED(retVal))
- {
- HX_VECTOR_DELETE(pAnim->m_ppPathCmd);
- if (ulNumCmd)
- {
- pAnim->m_ppPathCmd = new PathCmd* [ulNumCmd];
- if (pAnim->m_ppPathCmd)
- {
- for (UINT32 i = 0; i < ulNumCmd; i++)
- {
- pAnim->m_ppPathCmd[i] = (PathCmd*) cTmpArr[i];
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- pAnim->m_ulNumPathCmds = 0;
- }
- }
- if (FAILED(retVal))
- {
- for (UINT32 i = 0; i < ulNumCmd; i++)
- {
- PathCmd* pCmd = (PathCmd*) cTmpArr[i];
- HX_DELETE(pCmd);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- HX_VECTOR_DELETE(pTmp);
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- #endif // #if defined(XXXMEH_SPLINE_ANIMATION)
- BOOL CSmilParser::isDataURL(const char* pszURL)
- {
- BOOL bRet = FALSE;
- if (pszURL)
- {
- // Get the string length
- UINT32 ulLen = strlen(pszURL);
- if (ulLen)
- {
- // Skip any leading whitespace char
- // Make sure we have at least 5 characters
- // past the whitespace for "data:"
- UINT32 ulNumWS = strspn(pszURL, " trn");
- if (ulNumWS + 5 < ulLen)
- {
- // Advance to the beginning of non-whitespace
- pszURL += ulNumWS;
- // Check for "data:"
- if (strncmp(pszURL, "data:", 5) == 0)
- {
- bRet = TRUE;
- }
- }
- }
- }
- return bRet;
- }
- HX_RESULT CSmilParser::validateDataURL(const char* pszURL)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszURL)
- {
- if (isDataURL(pszURL))
- {
- // For complete syntax of data: URLs see:
- // data: URL RFC (http://www.cis.ohio-state.edu/cs/Services/rfc/rfc-text/rfc2397.txt)
- // URI syntax RFC (http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc2396.html)
- //
- // Initialize the return value to fail
- retVal = HXR_FAIL;
- // Look for "data:"
- const char* pCh = strstr(pszURL, "data:");
- if (pCh)
- {
- // Now find the ","
- pCh = strchr(pCh, ',');
- if (pCh)
- {
- // Skip past the ","
- ++pCh;
- // From now to the end of the string, enforce
- // the BNF's allowed characters
- BOOL bIllegalChar = FALSE;
- BOOL bEscapeSeq = FALSE;
- UINT32 ulNumEscape = 0;
- while (pCh && *pCh)
- {
- char c = *pCh++;
- if (bEscapeSeq)
- {
- if (isxdigit(c))
- {
- ++ulNumEscape;
- }
- else
- {
- bIllegalChar = TRUE;
- break;
- }
- if (ulNumEscape >= 2)
- {
- bEscapeSeq = FALSE;
- ulNumEscape = 0;
- }
- }
- else if (c == '%')
- {
- // Make sure the next two characters are
- // legally escaped
- bEscapeSeq = TRUE;
- }
- else if (!isalnum(c))
- {
- if (!(c == ';' ||
- c == '/' ||
- c == '?' ||
- c == ':' ||
- c == '@' ||
- c == '&' ||
- c == '=' ||
- c == '+' ||
- c == '$' ||
- c == ',' ||
- c == '-' ||
- c == '_' ||
- c == '.' ||
- c == '!' ||
- c == '~' ||
- c == '*' ||
- c == 0x27 || // "'"
- c == '(' ||
- c == ')'))
- {
- bIllegalChar = TRUE;
- break;
- }
- }
- }
- if (!bIllegalChar && !bEscapeSeq)
- {
- retVal = HXR_OK;
- }
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT
- CSmilParser::addBeginEventElement(SmilTimeValue* pTimeVal)
- {
- HX_RESULT rslt = HXR_OK;
- if (!m_pBeginEventList)
- {
- m_pBeginEventList = new CHXSimpleList;
- if (!m_pBeginEventList)
- {
- return HXR_OUTOFMEMORY;
- }
- }
- m_pBeginEventList->AddTail(pTimeVal);
- // Add it to the map
- addToBeginOrEndTimeMap(pTimeVal, SmilBeginTimeList);
- return rslt;
- }
- // /This function gets called on the fly whenever an event occurs, e.g.,
- // when the user clicks on an element.
- // ulEventTime is the time a click or other mouse event occured (which
- // should be roughly the current playback time. It is absolute, relative
- // to the beginning of the presentation (i.e., current clip). pEventElement
- // is the element where the event occurred (e.g., clicked on) and is
- // passed in here so that we can see if anyone in the beginEventList or
- // endEventList has a begin event or end event, respectively, equal to this
- // event on this pEventElement.
- HX_RESULT
- CSmilParser::tryToResolveBeginEndEvents(const char* pEventName,
- const char* pEventElementId,
- ULONG32 ulEventTime)
- {
- HX_RESULT ret = HXR_OK;
- // /XXEH- make sure casting is OK here; what if event time
- // is greater than 24.855 days (i.e., is > 0x7fffffff)?
- HX_ASSERT(ulEventTime < 0x7fffffff);
- INT32 lEventTime = (INT32)ulEventTime;
- if (pEventName && strlen(pEventName) &&
- // /pEventElementId can't be NULL and it can't be empty:
- pEventElementId && strlen(pEventElementId))
- {
- BOOL bIsResumeEvent = (0 == strcmp(pEventName, "resumeEvent"));
- CHXSimpleList* pBeginEventList = NULL;
- if (isTimeValueListPresent(pEventName, pEventElementId,
- SmilBeginTimeList, pBeginEventList))
- {
- LISTPOSITION pos = pBeginEventList->GetHeadPosition();
- while (pos)
- {
- BOOL bATimeWasResolved = FALSE;
- SmilTimeValue* pValue = (SmilTimeValue*) pBeginEventList->GetNext(pos);
- if (!pValue->m_pElement)
- {
- HX_ASSERT(pValue->m_pElement);
- continue;
- }
- if (!pValue->getIdRef() || !pValue->getEventName())
- {
- HX_ASSERT(pValue->getIdRef() && pValue->getEventName());
- continue;
- }
- // /Now go through all begin times that are awaiting this event
- // from this id'd element and resolve them:
- // /XXXEH- TODO: verify that SMIL Boston final spec still says to
- // resolve & use begin times first before doing so for end times:
- ret = pValue->m_pElement->resolveEventTimeValues(lEventTime,
- pEventName, pEventElementId,
- SmilBeginTimeList,
- bATimeWasResolved /*passed by ref*/);
- // /XXXEH- TODO: verify algorithm in SMIL Boston final draft that
- // says we should first resolve begin values awaiting this event
- // and act on the result, e.g., start an element, and THEN resolve
- // end values awaiting this event. The order that this is done
- // DOES affect playback in some cases (due to restart and other
- // factors).
- if (SUCCEEDED(ret) && bATimeWasResolved)
- {
- ret = insertElementWithPendingBeginOrEnd(
- pValue->m_pElement, lEventTime, SmilBeginTimeList);
- // /Found while fixing PR 79300 & PR 85885: an insert
- // failure is OK for resumeEvent:
- if (!SUCCEEDED(ret) &&
- bIsResumeEvent)
- {
- ret = HXR_OK;
- }
- }
- }// /end walking begin event list.
- }
- // /XXXEH- TODO: move the "setDelay..() calls, above,
- // to below this if () block; we only want to start an element if
- // it's not currently playing and if it has a begin time that is
- // not the same as its end time. All end times that are in the
- // past at the point of resolution of a begin time are ignored.
- // /XXXEH- ---make sure I got the above right! I think that
- // ---the SMIL Boston spec says that begin="5s" end="4s"
- // ---doesn't play because, at time 0, 4<5. However, end isn't
- // ---ignored if foo is clicked at 5s with the following timing:
- // ---begin="foo.activateEvent" end="4s" because end is in the past
- // ---at 5s and is thus ignored. (RIGHT???).
- CHXSimpleList* pEndEventList = NULL;
- if (SUCCEEDED(ret) &&
- // /Again, don't bother with end values since resumeEvent should
- // only be in begin list (and had better not be in end list):
- !bIsResumeEvent &&
- isTimeValueListPresent(pEventName, pEventElementId,
- SmilEndTimeList, pEndEventList))
- {
- LISTPOSITION pos = pEndEventList->GetHeadPosition();
- while (pos)
- {
- BOOL bATimeWasResolved = FALSE;
- SmilTimeValue* pValue = (SmilTimeValue*) pEndEventList->GetNext(pos);
- if (!pValue->m_pElement)
- {
- HX_ASSERT(pValue->m_pElement);
- continue;
- }
- if (!pValue->getIdRef() || !pValue->getEventName())
- {
- HX_ASSERT(pValue->getIdRef() && pValue->getEventName());
- continue;
- }
- // /Now go through all begin times that are awaiting this event
- // from this id'd element and resolve them:
- // /XXXEH- TODO: verify that SMIL Boston final spec still says to
- // resolve & use begin times first before doing so for end times:
- ret = pValue->m_pElement->resolveEventTimeValues(lEventTime,
- pEventName, pEventElementId,
- SmilEndTimeList,
- bATimeWasResolved /*passed by ref*/);
- // /XXXEH- TODO: verify algorithm in SMIL Boston final draft that
- // says we should first resolve begin values awaiting this event
- // and act on the result, e.g., start an element, and THEN resolve
- // end values awaiting this event. The order that this is done
- // DOES affect playback in some cases (due to restart and other
- // factors). Note: we may be able to combine above begin-list
- // for loop with this end-list for loop.
- if (SUCCEEDED(ret) && bATimeWasResolved)
- {
- ret = insertElementWithPendingBeginOrEnd(
- pValue->m_pElement, lEventTime,
- SmilEndTimeList);
- }
- }// /end walking begin event list.
- }
- }
- else
- {
- ret = HXR_UNEXPECTED;
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::addEndEventElement(SmilTimeValue* pTimeVal)
- {
- HX_RESULT rslt = HXR_OK;
- if (!m_pEndEventList)
- {
- m_pEndEventList = new CHXSimpleList;
- if (!m_pEndEventList)
- {
- return HXR_OUTOFMEMORY;
- }
- }
- m_pEndEventList->AddTail(pTimeVal);
- // Add it to the map
- addToBeginOrEndTimeMap(pTimeVal, SmilEndTimeList);
- return rslt;
- }
- HX_RESULT CSmilParser::addBeginMediaMarkerSyncElement(SmilTimeValue* pTmpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pTmpVal)
- {
- if (!m_pBeginMediaMarkerList)
- {
- m_pBeginMediaMarkerList = new CHXSimpleList();
- }
- if (m_pBeginMediaMarkerList)
- {
- m_pBeginMediaMarkerList->AddTail((void*) pTmpVal);
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::addEndMediaMarkerSyncElement(SmilTimeValue* pTmpVal)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pTmpVal)
- {
- if (!m_pEndMediaMarkerList)
- {
- m_pEndMediaMarkerList = new CHXSimpleList();
- }
- if (m_pEndMediaMarkerList)
- {
- m_pEndMediaMarkerList->AddTail((void*) pTmpVal);
- retVal = HXR_OK;
- }
- }
- return retVal;
- }
- HX_RESULT CSmilParser::resolveMediaMarkerTime(const char* pszID,
- const char* pszMarkerName,
- UINT32 ulMarkerTime,
- REF(BOOL) rbNeedHandleElements)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszID && pszMarkerName)
- {
- // Clear the handle elements flag
- rbNeedHandleElements = FALSE;
- // XXXMEH - TODO - linearly searching lists is not
- // a scalable solution - we should be looking up a
- // string in a map. Change how this is implemented
- //
- // First resolve the begin media marker list
- if (m_pBeginMediaMarkerList)
- {
- LISTPOSITION pos = m_pBeginMediaMarkerList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*) m_pBeginMediaMarkerList->GetNext(pos);
- if (pValue &&
- pValue->getIdRef() &&
- !strcmp(pszID, pValue->getIdRef()) &&
- pValue->getMarkerName() &&
- !strcmp(pszMarkerName, pValue->getMarkerName()))
- {
- // // Find out the scheduled start time for the element
- // // we are based off of. We already know that this
- // // element should be resolved since it is playing
- // // and resolving markers.
- // CSmilElement* pElement = findElement(pValue->getIdRef());
- // if (pElement)
- // {
- // UINT32 ulStart = 0;
- // HX_RESULT rv = pElement->getCurrentScheduledStartTime(ulStart);
- // if (SUCCEEDED(rv))
- // {
- // // Set this time as the "resolved" to time (this is
- // // the time without the offset)
- // pValue->setResolvedToTime((INT32) ulStart);
- // pValue->setWhenTimeWasResolved((INT32) ulStart);
- // }
- // }
- // Set the marker time
- pValue->setMarkerTime(ulMarkerTime);
- // XXXMEH - try this out - we want to now
- // treat this timeval as a sync-arc.
- addBeginTimeSyncElement(pValue->m_pElement);
- pValue->m_pElement->m_BeginEventSourceID = pValue->m_idRef;
- pValue->m_pElement->m_nBeginEventSourceTag = pValue->m_position;
- pValue->m_pElement->m_lBeginEventClockValue = pValue->getTimeOffset();
- m_pTimelineElementManager->addNotification(pValue->m_pElement->m_BeginEventSourceID,
- pValue->m_pElement->m_pTimelineElement);
- pValue->m_pElement->m_pTimelineElement->setDelayEventResolved(FALSE);
- // HX_RESULT rv = insertElementWithPendingBeginOrEnd(pValue->m_pElement,
- // SMILTIME_NEGATIVE_INFINITY,
- // SmilBeginTimeList);
- m_pTimelineElementManager->notify(pValue->m_idRef);
- m_pTimelineElementManager->notify(pValue->m_pElement->m_pNode->m_id);
- if (pValue->m_pElement->m_pTimelineElement->getParent())
- {
- pValue->m_pElement->m_pTimelineElement->getParent()->checkChildrenFillBehavior();
- }
- rbNeedHandleElements = TRUE;
- }
- }
- }
- // Now resolve the end media marker list
- if (m_pEndMediaMarkerList)
- {
- LISTPOSITION pos = m_pEndMediaMarkerList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*) m_pEndMediaMarkerList->GetNext(pos);
- if (pValue &&
- pValue->getIdRef() &&
- !strcmp(pszID, pValue->getIdRef()) &&
- pValue->getMarkerName() &&
- !strcmp(pszMarkerName, pValue->getMarkerName()))
- {
- // // Find out the scheduled start time for the element
- // // we are based off of. We already know that this
- // // element should be resolved since it is playing
- // // and resolving markers.
- // CSmilElement* pElement = findElement(pValue->getIdRef());
- // if (pElement)
- // {
- // UINT32 ulStart = 0;
- // HX_RESULT rv = pValue->m_pElement->getCurrentScheduledStartTime(ulStart);
- // if (SUCCEEDED(rv))
- // {
- // // Set this time as the "resolved" to time (this is
- // // the time without the offset)
- // pValue->setResolvedToTime((INT32) ulStart);
- // pValue->setWhenTimeWasResolved((INT32) ulStart);
- // }
- // }
- // Set the time that the marker resolved to
- pValue->setMarkerTime(ulMarkerTime);
- // XXXMEH - try this out - we want to now
- // treat this timeval as a sync-arc
- addEndTimeSyncElement(pValue->m_pElement);
- pValue->m_pElement->m_EndEventSourceID = pValue->m_idRef;
- pValue->m_pElement->m_nEndEventSourceTag = pValue->m_position;
- pValue->m_pElement->m_lEndEventClockValue = pValue->getTimeOffset();
- m_pTimelineElementManager->addNotification(pValue->m_pElement->m_EndEventSourceID,
- pValue->m_pElement->m_pTimelineElement);
- pValue->m_pElement->m_pTimelineElement->setDelayEventResolved(FALSE);
- // HX_RESULT rv = insertElementWithPendingBeginOrEnd(pValue->m_pElement,
- // SMILTIME_NEGATIVE_INFINITY,
- // SmilEndTimeList);
- m_pTimelineElementManager->notify(pValue->m_idRef);
- m_pTimelineElementManager->notify(pValue->m_pElement->m_pNode->m_id);
- if (pValue->m_pElement->m_pTimelineElement->getParent())
- {
- pValue->m_pElement->m_pTimelineElement->getParent()->checkChildrenFillBehavior();
- }
- rbNeedHandleElements = TRUE;
- }
- }
- }
- // Now resolve any clipBegin's which use this marker
- if (m_pClipBeginMarkerList)
- {
- LISTPOSITION pos = m_pClipBeginMarkerList->GetHeadPosition();
- while (pos)
- {
- CSmilElement* pElement = (CSmilElement*) m_pClipBeginMarkerList->GetNext(pos);
- if (pElement &&
- pElement->m_pNode &&
- !strcmp(pszID, pElement->m_pNode->m_id) &&
- !strcmp(pszMarkerName, pElement->m_pszClipBeginMarkerName))
- {
- // Set the clipBegin time to the resolved time
- pElement->m_ulClipBegin = ulMarkerTime;
- pElement->m_ulAuthoredClipBegin = ulMarkerTime;
- // Set the flag saying we're resolved
- pElement->m_bClipBeginMarkerResolved = TRUE;
- // If the delay and duration have been resolved
- // for this element, then we may have tried to
- // schedule this element previously and could
- // not because the clipBegin wasn't resolved.
- // If we have NOT attempted to schedule this
- // element, then don't try and schedule it now -
- // wait on the normal process.
- if (pElement->m_bWaitingOnClipBeginToResolve)
- {
- // Clear the flag
- pElement->m_bWaitingOnClipBeginToResolve = FALSE;
- // We DID try and schedule this element earlier,
- // and could not due to not knowing the
- // clipBegin. Therefore, now that we know the
- // clipBegin, we will attempt to insert it again.
- insertTimelineElement(pElement->m_pNode->m_id,
- pElement->m_ulDelay);
- // Set the flag saying we need to
- // call handleElements()
- rbNeedHandleElements = TRUE;
- }
- }
- }
- }
- // Now resolve any clipEnd's which use this marker
- if (m_pClipEndMarkerList)
- {
- LISTPOSITION pos = m_pClipEndMarkerList->GetHeadPosition();
- while (pos)
- {
- CSmilElement* pElement = (CSmilElement*) m_pClipEndMarkerList->GetNext(pos);
- if (pElement &&
- pElement->m_pNode &&
- !strcmp(pszID, pElement->m_pNode->m_id) &&
- !strcmp(pszMarkerName, pElement->m_pszClipEndMarkerName))
- {
- // Set the clipEnd time to the resolved time
- pElement->m_ulClipEnd = ulMarkerTime;
- // Set the flag saying we're resolved
- pElement->m_bClipEndMarkerResolved = TRUE;
- // If the delay and duration have been resolved
- // for this element, then we may have tried to
- // schedule this element previously and could
- // not because the clipEnd wasn't resolved.
- // If we have NOT attempted to schedule this
- // element, then don't try and schedule it now -
- // wait on the normal process.
- if (pElement->m_bWaitingOnClipEndToResolve)
- {
- // Clear the flag
- pElement->m_bWaitingOnClipEndToResolve = FALSE;
- // We DID try and schedule this element earlier,
- // and could not due to not knowing the
- // clipBegin. Therefore, now that we know the
- // clipBegin, we will attempt to insert it again.
- insertTimelineElement(pElement->m_pNode->m_id,
- pElement->m_ulDelay);
- // Set the flag saying we need to
- // call handleElements()
- rbNeedHandleElements = TRUE;
- }
- }
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT
- CSmilParser::addBeginTimeSyncElement(CSmilElement* pElement)
- {
- if (!m_pBeginTimeSyncList)
- {
- m_pBeginTimeSyncList = new CHXSimpleList;
- if (!m_pBeginTimeSyncList)
- {
- return HXR_OUTOFMEMORY;
- }
- }
- m_pBeginTimeSyncList->AddTail(pElement);
- return HXR_OK;
- }
- HX_RESULT
- CSmilParser::addEndTimeSyncElement(CSmilElement* pElement)
- {
- if (!m_pEndTimeSyncList)
- {
- m_pEndTimeSyncList = new CHXSimpleList;
- if (!m_pEndTimeSyncList)
- {
- return HXR_OUTOFMEMORY;
- }
- }
- m_pEndTimeSyncList->AddTail(pElement);
- return HXR_OK;
- }
- HX_RESULT
- CSmilParser::resolveSyncBaseElements()
- {
- HX_RESULT ret = HXR_OK;
- if (m_pBeginTimeSyncList)
- {
- CHXSimpleList::Iterator i;
- for (i = m_pBeginTimeSyncList->Begin();
- i != m_pBeginTimeSyncList->End(); ++i)
- {
- CSmilElement* pElement = (CSmilElement*)*i;
- LISTPOSITION lPos = NULL;
- if (NULL != pElement->m_pBeginTimeList)
- {
- lPos = pElement->m_pBeginTimeList->GetHeadPosition();
- }
- if (NULL == lPos) // /list is empty.
- {
- continue;
- }
- while (lPos && HXR_OK == ret)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*)
- (pElement->m_pBeginTimeList->GetNext(lPos));
- if (SmilTimeSyncBase == pValue->m_type)
- {
- INT32 offset = pValue->getTimeOffset();
- #if defined(_DEBUG) // /XXXEH- testing!:
- LONG32 lEffectiveResolvedToTime = 0;
- pValue->getEffectiveResolvedTime(
- lEffectiveResolvedToTime);
- // /This will change so assert for now so when we
- // change how these vars are used we won't miss this code
- HX_ASSERT(pValue->isTimeResolved()?
- offset==lEffectiveResolvedToTime : TRUE);
- #endif
- CSmilElement* pSyncElement =
- findElement((const char*)pValue->m_idRef);
- #if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
- if (!pSyncElement)
- #else
- // / "xxxx_repeat_copy_nnn" is OK since it's based on
- // xxxx.repeat(nnn) and is supposed to be treated as an
- // event and event id's don't have to exist:
- if (!pSyncElement && !strstr(
- (const char*)pValue->m_idRef, "_repeat_copy_") )
- #endif
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorNonexistentID,
- (const char*)pValue->m_idRef,
- pElement->m_pNode->m_ulTagStartLine);
- break;
- }
- // /XXXEH- why don't we need to do this Josh?:
- //else
- //{
- // pElement->m_BeginEventSourceID = pValue->m_idRef;
- // pElement->m_lBeginEventClockValue = offset;
- // pElement->m_nBeginEventSourceTag = pValue->m_position;
- //}
- }
- } // /end while(lPos ...).
- }
- }
- if (SUCCEEDED(ret) && m_pEndTimeSyncList)
- {
- CHXSimpleList::Iterator i;
- for (i = m_pEndTimeSyncList->Begin();
- i != m_pEndTimeSyncList->End(); ++i)
- {
- CSmilElement* pElement = (CSmilElement*)*i;
- LISTPOSITION lPos = NULL;
- if (NULL != pElement->m_pBeginTimeList)
- {
- lPos = pElement->m_pEndTimeList->GetHeadPosition();
- }
- if (NULL == lPos) // /list is empty.
- {
- continue;
- }
- while (lPos && HXR_OK == ret)
- {
- SmilTimeValue* pValue =
- (SmilTimeValue*)
- (pElement->m_pEndTimeList->GetNext(lPos));
- if (SmilTimeSyncBase == pValue->m_type)
- {
- INT32 offset = pValue->getTimeOffset();
- #if defined(_DEBUG) // /XXXEH- testing!:
- LONG32 lEffectiveResolvedToTime = 0;
- pValue->getEffectiveResolvedTime(
- lEffectiveResolvedToTime);
- // /This will change so assert for now so when we
- // change how these vars are used we won't miss this code
- HX_ASSERT(pValue->isTimeResolved()?
- offset==lEffectiveResolvedToTime : TRUE);
- #endif
- CSmilElement* pSyncElement =
- findElement((const char*)pValue->m_idRef);
- #if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
- if (!pSyncElement)
- #else
- // / "xxxx_repeat_copy_nnn" is OK since it's based on
- // xxxx.repeat(nnn) and is supposed to be treated as an
- // event and event id's don't have to exist:
- if (!pSyncElement && !strstr(
- (const char*)pValue->m_idRef, "_repeat_copy_") )
- #endif
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorNonexistentID,
- (const char*)pValue->m_idRef,
- pElement->m_pNode->m_ulTagStartLine);
- break;
- }
- // /XXXEH- why don't we need to do this Josh?:
- //else
- //{
- // pElement->m_EndEventSourceID = pValue->m_idRef;
- // pElement->m_lEndEventClockValue = offset;
- // pElement->m_nEndEventSourceTag = pValue->m_position;
- //}
- }
- } // /end while(lPos ...).
- }
- }
- return ret;
- }
- // /None of the descendants have yet been added to the timeline because we
- // needed to know what all of the descendants' begin times are resolved to
- // before we can know which to insert before playback, which not to insert
- // until during playback, and which never to insert. In the following
- // method (which is called before playback) we go ahead and insert the
- // first one, timewise (and lexically first if there is a tie; in that
- // case, we'll start the first and let the next interrupt the first during
- // playback). We also need to extend the duration of the excl to account
- // for the latest of all its descendants' begins:
- HX_RESULT
- CSmilParser::handleExclDescendants()
- {
- HX_RESULT ret = HXR_OK;
- // /XXXEH- see note in smlelem.cpp that starts with
- // "XXXEH- TODO: [optimization]: rather than inserting"...
- HX_RESULT retval = HXR_OK;
- BOOL bSomeScheduleWasChanged = FALSE;
- BOOL bDoHandleExclBeforePlaybackStarts = TRUE;
- retval = checkPendingBeginAndEndTimes(0, 0, // <-- use group 0 for all.
- bSomeScheduleWasChanged,
- 0, // /Recursion count is 0 when called externally.
- NULL, NULL, bDoHandleExclBeforePlaybackStarts);
- /*XXXEH: next, see if any excl has a child that has a resolved begin that is
- beyond the dur of the presentation (group); maybe keep track of that
- in setBeginTime() by keeping overall latest begin excl descendant
- and then, here, add that element if it's beyond end of presentation
- (or just extend dur of excl):
- */
- // /If we are in an excl and we are beginning after our excl parent's
- // current child-derived end, then go ahead and insert into the timeline,
- LISTPOSITION lPos = NULL;
- CHXSimpleList* pPendList = GetPendingBeginTimeList();
- if (pPendList)
- {
- lPos = pPendList->GetHeadPosition();
- }
- LONG32 lLatestGroup0BeginTimeSoFar = 0;
- LONG32 lLatestGroup0EndTimeSoFar = 0;
- SmilTimeValue* pTimeValOfGroup0LatestEndElem = NULL;
- while (lPos)
- {
- SmilTimeValue* pCurTimeVal =
- (SmilTimeValue*)pPendList->GetNext(lPos);
- if (pCurTimeVal && pCurTimeVal->m_pElement)
- {
- ULONG32 ulParentEnd = (UINT32)-1;
- SMILNode* pSyncBaseNode = getSyncAncestor(
- pCurTimeVal->m_pElement->m_pNode);
- BOOL bIsInExcl = hasAncestor(SMILExcl,
- pCurTimeVal->m_pElement->m_pNode);
- if (bIsInExcl && 0==pSyncBaseNode->m_nGroup)
- {
- if (pSyncBaseNode && pSyncBaseNode->m_pElement &&
- pSyncBaseNode->m_pElement->m_pTimelineElement)
- {
- // /XXXEH- TODO: handle case where endsync is
- // SMILEventSourceID and id matches m_pSourceElement->
- // m_pNode->m_id:
- // /XXXEH- TODO: also handle when sync parent has
- // indefinite end|dur:
- // /Now, see if we can extend our parent's duration and,
- // if so, see if we begin past that end time (if set) and,
- // if so, extend our parent's duration to our end time:
- if (!pSyncBaseNode->m_pElement->m_bHasExplicitEnd &&
- !pSyncBaseNode->m_pElement->m_bHasExplicitDur &&
- (SMILEventSourceFirst !=
- pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag &&
- SMILEventSourceID !=
- pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag) )
- {
- if ((UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDuration &&
- (UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDelay)
- {
- ulParentEnd = pSyncBaseNode->m_pElement->m_ulDelay +
- pSyncBaseNode->m_pElement->m_ulDuration;
- }
- LONG32 lEffectiveResolvedToTime = 0;
- HX_RESULT tmprslt =
- pCurTimeVal->getEffectiveResolvedTime(
- lEffectiveResolvedToTime);
- if (HXR_OK==tmprslt && lEffectiveResolvedToTime>0 &&
- !pCurTimeVal->m_pElement->m_bHasBeenScheduled)
- {
- // /We default to TRUE if it's MAX UINT32 because
- // duration of time containers hasn't neccessarily
- // been set by children yet:
- BOOL bDelayIsBeyondParentEnd = TRUE;
- if ((UINT32)-1 != ulParentEnd)
- {
- bDelayIsBeyondParentEnd = (ulParentEnd <
- pCurTimeVal->m_pElement->m_ulDelay);
- }
- if (bDelayIsBeyondParentEnd &&
- lEffectiveResolvedToTime >
- lLatestGroup0BeginTimeSoFar)
- {
- lLatestGroup0BeginTimeSoFar =
- lEffectiveResolvedToTime;
- lLatestGroup0EndTimeSoFar =
- lEffectiveResolvedToTime +
- ( (UINT32)-1 == pCurTimeVal->
- m_pElement->m_ulDuration? 10 :
- pCurTimeVal->m_pElement->m_ulDuration);
- pTimeValOfGroup0LatestEndElem = pCurTimeVal;
- // /Fix related to PR 56690: excl itself needs
- // to know that it's got at least one child
- // with a scheduled begin time(s):
- HX_ASSERT(pSyncBaseNode->m_pElement->m_pTimelineElement);
- if (pSyncBaseNode->m_pElement->m_pTimelineElement)
- {
- pSyncBaseNode->m_pElement->m_pTimelineElement->
- setHasChildWithScheduledBegin(TRUE);
- }
- }
- }
- }
- }
- }
- }
- }
- if (lLatestGroup0EndTimeSoFar > 0 && pTimeValOfGroup0LatestEndElem)
- {
- #if defined(XXXEH_THE_FOLLOWING_BREAKS_PAUSE_RESUME_IN_EXCL__NEEDS_REVISIT)
- // /XXXEH- TODO: either remove from pendingBeginList or *don't*
- // insert here but rather insert a dummy source (or *somehow* tell
- // the timeline to stay open past lLatestGroup0BeginTimeSoFar):
- // See "BUG-20010427_vidDoesntPause(IThinkDueToSecondOneBeing"...
- // ..."AddedPriorToPlaybackIfParentDurIs0sAtTheTime...).smil"
- insertTimelineElement(pTimeValOfGroup0LatestEndElem->m_pElement->
- m_pTimelineElement->m_pID, lLatestGroup0BeginTimeSoFar);
- #else
- HX_ASSERT(1); // /breakpoint-only code.
- #endif
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::parseSmil1SyncbaseValue(const char* pCh,
- CSmilElement* pElement,
- SMILSyncAttributeTag nTag)
- {
- HX_RESULT ret = HXR_OK;
- BOOL bParseError = FALSE;
- BOOL bHasEvent = TRUE;
- UINT32 clockValue = 0;
- char* pIdTag = new char[strlen(pCh)+1];
- char* pEvent = new char[strlen(pCh)+1];
- pIdTag[0] = 0;
- pEvent[0] = 0;
- BOOL bIsSMIL_1_0_idRef = TRUE;
- if (!strncmp(pCh, "id(", 3))
- {
- pCh += 3; // skip over 'id('
- }
- else // /SMIL 2.0 id-ref can simply be the id val.
- {
- bIsSMIL_1_0_idRef = FALSE;
- }
- int i = 0;
- while(*pCh && (*pCh != ')'))
- {
- pIdTag[i++] = *pCh++;
- }
- if(*pCh == ')' || !bIsSMIL_1_0_idRef)
- {
- pIdTag[i] = 0;
- // lookup ID to see if it references an existing entity,
- // otherwise it is an error
- void* pDummy = NULL;
- // /XXXEH- TODO: make sure this is not only a valid ID,
- // but is an immediate child of pElement (as per the SMIL 2.0 spec):
- if(!m_pIDMap->Lookup(pIdTag, pDummy))
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pCh,
- pElement->m_pNode->m_ulTagStartLine);
- bParseError = TRUE;
- }
- else
- {
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_BeginEventSourceID = pIdTag;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_EndEventSourceID = pIdTag;
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_EndsyncEventSourceID = pIdTag;
- }
- break;
- default:
- break;
- }
- }
- delete[] pIdTag;
- if(strlen(pCh) > 2)
- {
- if(nTag != SMILSyncAttrEndsync)
- {
- pCh++; // skip over ')'
- pCh++; // skip over '('
- i = 0;
- while(*pCh && (*pCh != ')'))
- {
- pEvent[i++] = *pCh++;
- }
- if(*pCh == ')')
- {
- pEvent[i] = 0;
- }
- else
- {
- bParseError = TRUE;
- }
- }
- else
- {
- bParseError = TRUE;
- }
- }
- else
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceID;
- bHasEvent = FALSE;
- }
- else
- {
- bParseError = TRUE;
- }
- }
- }
- else
- {
- bParseError = TRUE;
- }
- if(bParseError)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pCh,
- pElement->m_pNode->m_ulTagStartLine);
- }
- else if(bHasEvent)
- {
- SMILEventSourceTag eSourceTag = SMILEventSourceNone;
- INT32 lEventClockValue = 0;
- if(strcmp(pEvent, "begin") == 0)
- {
- eSourceTag = SMILEventSourceBegin;
- }
- else if(strcmp(pEvent, "end") == 0)
- {
- eSourceTag = SMILEventSourceEnd;
- }
- else
- {
- // eat white space, and + or - if it is there..
- while (isspace(*pEvent))
- {
- ++pEvent;
- }
- BOOL bPos = TRUE;
- if (*pEvent == '+')
- {
- ++pEvent;
- }
- else if (*pEvent == '-')
- {
- ++pEvent;
- bPos = FALSE;
- }
- UINT32 clockValue;
- if(HXR_OK == parseClockValue(pEvent, clockValue))
- {
- eSourceTag = SMILEventSourceClock;
- }
- else
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pEvent,
- pElement->m_pNode->m_ulTagStartLine);
- }
- lEventClockValue = (bPos ? clockValue:-1 * clockValue );
- }
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_nBeginEventSourceTag = eSourceTag;
- pElement->m_lBeginEventClockValue = lEventClockValue;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_nEndEventSourceTag = eSourceTag;
- pElement->m_lEndEventClockValue = lEventClockValue;
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_nEndsyncEventSourceTag = eSourceTag;
- }
- break;
- default:
- break;
- }
- }
- delete[] pEvent;
- return ret;
- }
- BOOL
- CSmilParser::EstablishBeginTimeList()
- {
- BOOL bNotNull = TRUE;
- if (!m_pPendingBeginTimeList)
- {
- m_pPendingBeginTimeList = new CHXSimpleList;
- bNotNull = (NULL != m_pPendingBeginTimeList);
- }
- return bNotNull;
- }
- BOOL
- CSmilParser::EstablishEndTimeList()
- {
- BOOL bNotNull = TRUE;
- if (!m_pPendingEndTimeList)
- {
- m_pPendingEndTimeList = new CHXSimpleList;
- bNotNull = (NULL != m_pPendingEndTimeList);
- }
- return bNotNull;
- }
- BOOL
- CSmilParser::EstablishBeginEventList()
- {
- BOOL bNotNull = TRUE;
- if (!m_pBeginEventList)
- {
- m_pBeginEventList = new CHXSimpleList;
- bNotNull = (NULL != m_pBeginEventList);
- }
- return bNotNull;
- }
- BOOL
- CSmilParser::EstablishEndEventList()
- {
- BOOL bNotNull = TRUE;
- if (!m_pEndEventList)
- {
- m_pEndEventList = new CHXSimpleList;
- bNotNull = (NULL != m_pEndEventList);
- }
- return bNotNull;
- }
- HX_RESULT
- CSmilParser::insertElementWithPendingBeginOrEnd(CSmilElement* pElement,
- INT32 lCurTimeInGroupTime,
- SmilTimingListType listType)
- {
- HX_RESULT retval = HXR_OK;
- LISTPOSITION lPos = NULL;
- LISTPOSITION lPrev = NULL;
- LISTPOSITION lPosCurVal = NULL;
- SmilTimeValue* pNextResolvedValue = NULL;
- UINT32 ulSyncBaseTime = getSyncBaseTimeInGroupTimeCoords(pElement->m_pNode);
- INT32 lCurTimeInSyncBaseTime = lCurTimeInGroupTime - (LONG32)ulSyncBaseTime;
- CHXSimpleList* pWhichList = NULL;
- if (SmilBeginTimeList == listType) // /insert begin time:
- {
- if (!EstablishBeginTimeList())
- {
- retval = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pWhichList = m_pPendingBeginTimeList;
- }
- else if (SmilEndTimeList == listType)// /insert end time:
- {
- if (!EstablishEndTimeList())
- {
- retval = HXR_OUTOFMEMORY;
- goto cleanup;
- }
- pWhichList = m_pPendingEndTimeList;
- }
- else
- {
- HX_ASSERT(SmilBeginTimeList == listType ||
- SmilEndTimeList == listType);
- }
- if (NULL == pWhichList)
- {
- retval = HXR_FAILED;
- goto cleanup;
- }
- lPos = pWhichList->GetHeadPosition();
- // /First, we need to get the next resolved time of pElement
- // that is at or after lCurTimeInGroupTime:
- retval = pElement->getNextResolvedTimeValue(pNextResolvedValue,
- lCurTimeInGroupTime, lCurTimeInSyncBaseTime,
- listType, /* Don't need list of resolved times:*/ NULL);
- if (!SUCCEEDED(retval) || NULL==pNextResolvedValue ||
- !pNextResolvedValue->isTimeResolved())
- {
- // /XXXEH- we shouldn't get here since we should never insert an
- // element in this list that doesn't have a future resolved
- // begin/end (depends on listType) time:
- HX_ASSERT(0);
- goto cleanup;
- }
- // /XXXEH- see "TODO: we ONLY want to..." comment below before believing
- // the following:
- // /Remove existing node in list if it's got same id and a later
- // resolved time; we only want each element once in the list and
- // list needs to be in order based on the next resolved begin time:
- // /XXXEH- TODO: we're searching the list twice; combine the following
- // with the subsequent while() loop:
- while (lPos)
- {
- lPosCurVal = lPos;
- SmilTimeValue* pCurNode =
- (SmilTimeValue*)pWhichList->GetNext(lPos);
- if (pCurNode && pCurNode->m_pElement &&
- pCurNode->m_pElement->m_pNode &&
- pCurNode->m_pElement->m_pNode->m_id == pElement->m_pNode->m_id)
- {
- /* /XXXEH- TODO: we ONLY want to remove duplicates of times that
- are based on exactly the same event-base or sync-base reference,
- e.g., begin="foo.activateEvent+5s; foo.activateEvent+8s" will
- put two distinct begin times in this list when foo is clicked.
- Modify the following so that it only removes this duplicate if it has
- the same sync-base/event-base id and sync-type/event-type value (including
- same offset):
- pWhichList->RemoveAt(lPosCurVal);
- */
- }
- else
- {
- // /(In)sanity check: no node should be NULL in this list and no
- // non-NULL node should have NULL m_pElement:
- HX_ASSERT(pCurNode && pCurNode->m_pElement &&
- pCurNode->m_pElement->m_pNode);
- }
- }
- lPos = pWhichList->GetHeadPosition();
- lPrev = lPos;
- lPosCurVal = lPos;
- // /Now, find where in the list to insert this new one based on temporal
- // order:
- while(lPos)
- {
- SmilTimeValue* pCurNode =
- (SmilTimeValue*)pWhichList->GetNext(lPos);
- if (!pCurNode || !pCurNode->m_pElement)
- {
- HX_ASSERT(pCurNode && pCurNode->m_pElement);
- continue;
- }
- // /To help fix one of the problems in PR 85885 & PR 79300, we need to
- // make sure the curTime passed in is in syncBase time space, not group
- // time, otherwise 2nd-or-later-in-seq children with scheduled begins
- // will be treated as in the past or otherwise with wrong begin time:
- UINT32 ulCurNodeSyncBaseTime = getSyncBaseTimeInGroupTimeCoords(
- pCurNode->m_pElement->m_pNode);
- INT32 lCurNodeCurTimeInSyncBaseTime = lCurTimeInGroupTime -
- (LONG32)ulCurNodeSyncBaseTime;
- // /This is the next resolved time of the current list node that
- // we're comparing to pElement's next resolved time:
- SmilTimeValue* pNextTimeValueOfCurElement = NULL;
- retval = pCurNode->m_pElement->getNextResolvedTimeValue(
- pNextTimeValueOfCurElement, lCurTimeInGroupTime,
- lCurNodeCurTimeInSyncBaseTime, listType,
- /* Don't need list of resolved times:*/ NULL);
- if (!SUCCEEDED(retval) || NULL==pNextTimeValueOfCurElement ||
- !pNextTimeValueOfCurElement->isTimeResolved())
- {
- // /XXXEH- we shouldn't get here because we should never have
- // inserted an element in this list that doesn't have a future
- // resolved begin:
- /// /XXXEH- not so sure about that... HX_ASSERT(0);
- continue;
- }
- LONG32 lCurNodeEffectiveResolvedTime;
- HX_RESULT rv1 = pNextTimeValueOfCurElement->getEffectiveResolvedTime(
- lCurNodeEffectiveResolvedTime);
- if (!SUCCEEDED(rv1))
- {
- continue;
- }
- // /This is the next resolved time of pElement:
- LONG32 lElementValueEffectiveResolvedTime;
- HX_RESULT rv2 = pNextResolvedValue->getEffectiveResolvedTime(
- lElementValueEffectiveResolvedTime);
- if (!SUCCEEDED(rv2))
- {
- retval = rv2;
- goto cleanup; // /error; we can't proceed.
- }
- // /See if pElement's next resolved time is less than the current
- // list node's:
- if (lCurNodeEffectiveResolvedTime>lElementValueEffectiveResolvedTime)
- {
- pWhichList->InsertBefore(lPrev, pNextResolvedValue);
- retval = HXR_OK;
- goto cleanup;
- }
- lPrev = lPos;
- }
- // /Nothing was inserted in the above while(), so insert it at end:
- pWhichList->AddTail(pNextResolvedValue);
- cleanup:
- return retval;
- }
- HX_RESULT
- CSmilParser::handlePendingScheduling(INT32 lCurTimeInGroupTime,
- INT16 iCurrentGroupIndex,
- REF(BOOL) bSomeScheduleWasChanged,
- /*OUT*/ CHXSimpleList* pPauseDisplayHideElementList,
- /*OUT*/ CHXSimpleList* pPauseDisplayDisableElementList)
- {
- HX_RESULT retval = HXR_OK;
- HX_RESULT tmpretval = HXR_OK;
- bSomeScheduleWasChanged = FALSE;
- retval = checkPendingBeginAndEndTimes(lCurTimeInGroupTime, iCurrentGroupIndex,
- // /This is set to TRUE if any element's begin and/or end time
- // gets updated to a new time:
- bSomeScheduleWasChanged,
- // /Recursion count is 0 when called externally:
- 0,
- pPauseDisplayHideElementList,
- pPauseDisplayDisableElementList,
- FALSE);
- return retval;
- }
- typedef enum
- {
- SMILTimelineStatusUnknown = 0
- , SMILTimelineStatusNeverScheduled
- , SMILTimelineStatusStartScheduledForLater
- , SMILTimelineStatusCurrentlyPlaying
- , SMILTimelineStatusFinishedPlaying
- , SMILTimelineStatusCurrentlyPaused
- , SMILTimelineStatusCurrentlyPausedAndRestarting // /For PR 62397 fix.
- } SMILTimelineStatus;
- /* This looks to see if any elements in the lists have a begin or end time
- * that is not yet accounted for in the timeline and that is now at or
- * earlier than lCurTime. If any such begin times are found, then a track
- * that's playing that is associated with that element may get restarted
- * (depending on the element's restart value) and if any such end times are
- * found then the track that's playing that's associated with that element
- * will get stopped. Note: Each list is sorted temporally so that the
- * first element is the earliest, and each element whose time is reached
- * gets removed.
- *
- * // /XXXEH- TODO: when a new begin time of an excl becomes scheduled
- * // within this function, be sure to schedule an end for all its siblings.
- *
- * Returns HXR_FAILED or HXR_UNEXPECTED on error, returns TRUE in
- * bREFSomeScheduleWasChanged if any begin and/or end time became used to
- * either start, restart, or end any element.
- */
- HX_RESULT
- CSmilParser::checkPendingBeginAndEndTimes(INT32 lCurTime,
- INT16 iCurrentGroupIndex,
- REF(BOOL) bREFSomeScheduleWasChanged, INT32 lRecursionCount,
- /*OUT*/ CHXSimpleList* pPauseDisplayHideElementList,
- /*OUT*/ CHXSimpleList* pPauseDisplayDisableElementList,
- BOOL bDoHandleExclBeforePlaybackStarts)
- {
- HX_RESULT retval = HXR_OK;
- bREFSomeScheduleWasChanged = FALSE;
- m_lLastCheckPendingTime = lCurTime;
- HX_ASSERT(lRecursionCount<=MAX_PENDING_CHECK_CALLDEPTH);
- // /Handle begin times that are ready to go:
- LISTPOSITION lPos = NULL;
- if (m_pPendingBeginTimeList)
- {
- lPos = m_pPendingBeginTimeList->GetHeadPosition();
- }
- // /Keep track of this at the excl-element level to allow multiple excl's
- // to go through this loop as happens, for instance, when multiple groups
- // exist in the presentation and more than one has an excl in it, or when
- // multiple excl's begin at 0s in the same par:
- CHXMapStringToOb* pExclChildAddedBeforePlayback = new CHXMapStringToOb();
- SmilTimeValue* pTimeValEndToggleToBeIgnored = NULL;
- // /Go through and see if anybody has a begin time that's ready to become
- // their active begin time:
- while (lPos && HXR_OK == retval)
- {
- LISTPOSITION lPosOfCurTmpVal = lPos;
- // /Gets val at lPos and then moves lPos to next node in list:
- SmilTimeValue* pTmpVal =
- (SmilTimeValue*)m_pPendingBeginTimeList->GetNext(lPos);
- if (!pTmpVal || !pTmpVal->m_pElement ||
- !pTmpVal->m_pElement->m_pNode)
- {
- // /List shouldn't have an empty node or a node w/NULL element:
- HX_ASSERT(pTmpVal && pTmpVal->m_pElement &&
- pTmpVal->m_pElement->m_pNode);
- // /Get rid of it from the list:
- m_pPendingBeginTimeList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- // /Fixes PR 54281 (final timing fix after core nested-meta fix):
- // Don't use this timeValue if it's element is not in the current
- // group, otherwise we'll start pending tracks based on prior group's
- // onTimeSync times (each group has zero-based OnTimeSyncs()).
- // NOTE: this can only happen in an excl which is the only place a
- // resolved-begin-before-playback element will end up in the pending
- // list:
- if (pTmpVal->m_pElement->m_pNode->m_nGroup != iCurrentGroupIndex &&
- // /If this is -1, then no source has ever been added to the
- // core. Helps fix cases where event-begun media is first
- // media to play:
- iCurrentGroupIndex != -1 &&
- // /OK to do all time-0 ones prior to playback commencing
- // because they're all OK to pre-schedule, anyway:
- !bDoHandleExclBeforePlaybackStarts)
- {
- continue;
- }
- LONG32 lEffectiveResolvedTime = 0;
- LONG32 lSyncbaseDelayAddedToResolvedTime = 0;
- HX_RESULT tmprslt =
- pTmpVal->getEffectiveResolvedTime(lEffectiveResolvedTime);
- if (HXR_OK!=tmprslt)
- {
- // /No element should ever have been inserted in this list if it
- // didn't have a resolved time so we shouldn't get here!
- HX_ASSERT(HXR_OK==tmprslt);
- // /Get rid of it from the list:
- m_pPendingBeginTimeList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- SMILNode* pExclAncestor = getSpecificAncestor(SMILExcl,
- pTmpVal->m_pElement->m_pNode);
- SMILNode* pSyncAncestor = getSyncAncestor(pTmpVal->m_pElement->m_pNode);
- // /If we're in an excl and being handled prior to playback starting
- // (or after playback starts but our excl parent has a begin offset),
- // then we may not have our delay set yet by our parent in which
- // case we need to add our parent delay to lEffectiveResolvedTime:
- // This *only* applies to scheduled (non-event) begin times that
- // resolved at time 0 before being able to adjust for parent delay
- // offset:
- if (0 == pTmpVal->getWhenTimeWasResolved() &&
- 0 == lEffectiveResolvedTime &&
- pExclAncestor &&
- pTmpVal->m_pElement && pTmpVal->m_pElement->m_pNode &&
- (UINT32)-1 == pTmpVal->m_pElement->m_ulDelay &&
- (SmilTimeOffset == pTmpVal->m_type ||
- SmilTimeClockValue == pTmpVal->m_type ||
- SmilTimeWallclock == pTmpVal->m_type))
- {
- if (pSyncAncestor && pSyncAncestor->m_pElement &&
- (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
- {
- if (bDoHandleExclBeforePlaybackStarts)
- {
- pTmpVal->setResolvedToTime(pSyncAncestor->m_pElement->m_ulDelay);
- lEffectiveResolvedTime += pSyncAncestor->m_pElement->m_ulDelay;
- lSyncbaseDelayAddedToResolvedTime =
- pSyncAncestor->m_pElement->m_ulDelay;
- }
- else
- {
- // /We'll get here if excl parent is not 1st child of a seq.
- HX_ASSERT(1 || "XXXEH- BUG-20010516_PR52110(simplifiedVersionMaybe)....smil");
- lEffectiveResolvedTime += pSyncAncestor->m_pElement->m_ulDelay;
- lSyncbaseDelayAddedToResolvedTime =
- pSyncAncestor->m_pElement->m_ulDelay;
- }
- }
- else
- {
- // /Parent has unresolved delay so we don't want to do
- // anything with its children yet:
- continue;
- }
- }
- // /If our effectiveResolvedTime is later than zero and we're in an
- // excl and have a clock-type time, then our time is still in parent
- // coordinates and not in overall timeline coordinates like lCurTime
- // is. We need to adjust the lEffectiveResolvedTime up by the delay
- // of our parent for later comparison to lCurTime:
- else if (pExclAncestor &&
- pTmpVal->m_pElement && pTmpVal->m_pElement->m_pNode &&
- (UINT32)-1 == pTmpVal->m_pElement->m_ulDelay &&
- (SmilTimeOffset == pTmpVal->m_type ||
- SmilTimeClockValue == pTmpVal->m_type ||
- SmilTimeWallclock == pTmpVal->m_type))
- {
- // /In an excl, we don't want to use clock value times; we want
- // use resolved-to times since we're treating these clock times
- // more like events. getEffectiveResolvedTime(), above, just
- // returns the offset if it's a clock time, i.e., it is not in
- // player time but rather in local sync-base time because
- // clock times usually are used prior to playback as local times:
- INT32 lResolvedToTime = pTmpVal->getResolvedToTimeWithoutOffset();
- if (pSyncAncestor && pSyncAncestor->m_pElement &&
- (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
- {
- lEffectiveResolvedTime += pSyncAncestor->m_pElement->m_ulDelay;
- // /If this is an excl-deferred track, then lResolvedToTime
- // could be >0 and != lEffectiveResolvedTime (as in PR 55936).
- pTmpVal->setResolvedToTime(lEffectiveResolvedTime);
- pTmpVal->setWhenTimeWasResolved(lCurTime);
- }
- else
- {
- // /Parent has unresolved delay so we don't want to do
- // anything with its children yet:
- continue;
- }
- }
- ULONG32 ulActualStartTime = 0;
- ULONG32 ulActualStopTime = 0;
- HX_RESULT pnrStart =
- pTmpVal->m_pElement->getCurrentScheduledStartTime(
- ulActualStartTime);
- LONG32 lElementCurBeginTime = (LONG32)ulActualStartTime;
- HX_RESULT pnrStop =
- pTmpVal->m_pElement->getCurrentScheduledStopTime(
- ulActualStopTime);
- LONG32 lElementCurEndTime = (LONG32)ulActualStopTime;
- SMILTimelineStatus curSMILTimelineStatus = SMILTimelineStatusUnknown;
- BOOL bTrackIsFinishedAndFrozen = FALSE;
- BOOL bCurElementIsTimeContainer =
- isTimeContainerObject(pTmpVal->m_pElement->m_pNode);
- if (!pTmpVal->m_pElement->m_bInsertedIntoTimeline)
- {
- curSMILTimelineStatus = SMILTimelineStatusNeverScheduled;
- }
- else
- {
- HX_ASSERT(HXR_OK == pnrStart &&
- (UINT32)-1 != lElementCurBeginTime &&
- SMILTIME_INFINITY != lElementCurBeginTime);
- if (lElementCurBeginTime > lCurTime)
- {
- curSMILTimelineStatus =
- SMILTimelineStatusStartScheduledForLater;
- }
- else
- {
- // /We need to check if this is a paused track and, if so,
- // extend its end time by how long it was paused:
- if (lEffectiveResolvedTime <= lCurTime &&
- pTmpVal->isResumeEvent() &&
- pTmpVal->m_pElement->m_pHandler)
- {
- CSmilTimelineElement* pParent = pTmpVal->m_pElement->
- m_pTimelineElement->getParent();
- pTmpVal->m_pElement->prepForResumeInExcl();
- // /First, let's check to see if it's got an explicit end
- // time that's already in the past (Interop Timing #25.8):
- BOOL bEndIsInThePast =
- (pTmpVal->m_pElement->m_bHasExplicitEnd &&
- pTmpVal->m_pElement->m_bEndOffsetSet &&
- pTmpVal->m_pElement->m_lEndOffset <= lCurTime);
- if (!bEndIsInThePast)
- {
- curSMILTimelineStatus =
- SMILTimelineStatusCurrentlyPaused;
- LONG32 lPauseTime = pTmpVal->getPauseTime();
- HX_ASSERT(lPauseTime < lCurTime);
- LONG32 lPauseDuration = lCurTime>lPauseTime?
- (lCurTime-lPauseTime) : 0;
- ULONG32 ulDur = pTmpVal->m_pElement->m_ulDuration;
- HX_ASSERT(pTmpVal->m_pElement->m_ulAnticipatedPauseDur <
- WAY_IN_THE_FUTURE);
- if (pTmpVal->m_pElement->m_ulAnticipatedPauseDur < ulDur)
- {
- // /Helps fix PR 86107: reduce dur by what we thought
- // it was supposed to extend by (which may differ
- // from actual pause time) and then add actual pause
- // duration to the original value, below, to get
- // total actual duration including pause:
- ulDur -= pTmpVal->m_pElement->m_ulAnticipatedPauseDur;
- }
- // /Adding the conditional to this "else" re-fixes
- // PR 85896 (& dup 79288) which were broken by PR 86107
- // fix, and helps fix PR 100601. This might be a valid
- // case where the duration of the pausing element was
- // not yet set at time of pause (i.e., it was still
- // 0xFFFFFFFF) or it was indefinite; we shouldn't adjust
- // "back" if we never adjusted forward:
- else if (pTmpVal->m_pElement->m_ulAnticipatedPauseDur <
- WAY_IN_THE_FUTURE)
- {
- ulDur = 0;
- HX_ASSERT(ulDur);
- }
- // /Make sure this doesn't get used now that it's resuming:
- pTmpVal->m_pElement->m_ulAnticipatedPauseDur = 0;
- if (lPauseDuration > 0 && (UINT32)-1 != ulDur &&
- SMILTIME_INFINITY != ulDur &&
- (!pTmpVal->m_pElement->m_bIndefiniteDuration ||
- pTmpVal->m_pElement->m_bIndefiniteEnd))
- {
- // /Hleps Fix PR 85896: don't add pauseDur to
- // indefinite/unresolved duration:
- if (WAY_IN_THE_FUTURE != ulDur)
- {
- ulDur += lPauseDuration;
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %s;tresetting duration from %lu to %lu (delay=%lu, pauseDuration=%ld)n",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- pTmpVal->m_pElement->m_ulDuration, ulDur, pTmpVal->m_pElement->m_ulDelay, lPauseDuration);
- ::fclose(f1);
- }
- #endif
- pTmpVal->m_pElement->m_pTimelineElement->
- resetDuration(ulDur);
- // /Helps fix PR 86106 (all 3 versions)
- // /Force smildocrender to HandleElements():
- bREFSomeScheduleWasChanged = TRUE;
- }
- else
- {
- // /Fix for PR 85896: make sure core doesn't
- // extend past the "indefinite/unresolved" time
- // due to pause-extended track; tell core to
- // reduce dur by curTime to keep the same end:
- UINT32 ulCurTime =
- lCurTime<0? 0 : (UINT32)lCurTime;
- resetTimelineElementDuration(
- pTmpVal->m_pElement->m_pNode->m_id,
- ulDur - ulCurTime, ulDur);
- // /Force smildocrender to HandleElements():
- bREFSomeScheduleWasChanged = TRUE;
- }
- }
- retval = pTmpVal->m_pElement->m_pHandler->
- handleTrackResuming(
- (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- (INT32)pTmpVal->m_pElement->m_pNode->m_nGroup);
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %s;thandleTrackResuming() returned 0x%08xn",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id, retval);
- ::fclose(f1);
- }
- #endif
- if (pParent)
- {
- // /Helps fix PR 53175 (& 54540): resuming after
- // another ends should cause the one that ended to
- // disappear (if its fill="freeze" or "remove"):
- pParent->checkChildrenFillBehavior();
- }
- }
- else
- {
- if (pParent)
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %s;tcalling checkChildrenFillBehavior() "
- "because someone's end has been surpassedn",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id);
- ::fclose(f1);
- }
- #endif
- // /Make sure it has chance to be visibly removed:
- pParent->checkChildrenFillBehavior();
- }
- // /Get rid of it from the list:
- m_pPendingBeginTimeList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- }
- else if (lElementCurEndTime > lCurTime)
- {
- curSMILTimelineStatus =
- SMILTimelineStatusCurrentlyPlaying;
- // /Fixes PR 62397: need to check if it's a paused track
- // being restarted; if so, remove its resume event and
- // allow its currently-playing sibling to be removed:
- if (lEffectiveResolvedTime <= lCurTime &&
- // /Make sure it's paused; PR 50588's par *was*
- // passing this if() test but was not paused; it
- // has a par with begin="0s;4s" and end > 4s:
- pTmpVal->m_pElement->m_bIsPausedInExcl &&
- pTmpVal->m_pElement->m_pHandler)
- {
- // /Resume events should have been handled above:
- HX_ASSERT(!pTmpVal->isResumeEvent());
- curSMILTimelineStatus =
- SMILTimelineStatusCurrentlyPausedAndRestarting;
- // /Next, remove the resume event from the event list
- // since this track is restarting so its old, paused,
- // track goes away:
- // /Also, make sure that any paused sibling awaiting
- // the current (restarting) one's end now points to
- // the next-in-pause-queue element instead:
- SmilTimeValue* pTmVlCurElementResumeEvent = NULL;
- SmilTimeValue*
- pTmVlPausedSiblResumesWhenCurElementEnds = NULL;
- LISTPOSITION listPos = NULL;
- HX_ASSERT(m_pBeginEventList);
- if (m_pBeginEventList)
- {
- listPos = m_pBeginEventList->GetHeadPosition();
- while (listPos)
- {
- LISTPOSITION lPosOfCurTmpTimeValue = listPos;
- // /Gets val at lPos then moves lPos to next node:
- SmilTimeValue* pTmpTimeValue = (SmilTimeValue*)
- m_pBeginEventList->GetNext(listPos);
- if (!pTmpTimeValue ||
- !pTmpTimeValue->m_pElement)
- {
- // /List shouldn't have an empty or NULL node:
- HX_ASSERT(pTmpTimeValue &&
- pTmpTimeValue->m_pElement);
- continue;
- }
- if (pTmpTimeValue->m_pElement ==
- pTmpVal->m_pElement &&
- pTmpTimeValue->isResumeEvent())
- {
- // /Get rid of it from the pending list:
- m_pBeginEventList->RemoveAt(lPosOfCurTmpTimeValue);
- // Get rid of it from the map
- removeFromBeginOrEndTimeMap(pTmpTimeValue, SmilBeginTimeList);
- pTmVlCurElementResumeEvent = pTmpTimeValue;
- if (pTmVlPausedSiblResumesWhenCurElementEnds)
- {
- // /The one (if any) that was paused by
- // the last play of this should instead
- // await the resume event of the next-in-
- // line element on the "pause queue":
- pTmVlPausedSiblResumesWhenCurElementEnds->
- m_idRef = pTmpTimeValue->m_idRef;
- break; // /We found both so we're done.
- }
- }
- else if (pTmpTimeValue->m_idRef ==
- pTmpVal->m_pElement->m_pNode->m_id &&
- pTmpTimeValue->isResumeEvent())
- {
- pTmVlPausedSiblResumesWhenCurElementEnds =
- pTmpTimeValue;
- // /The one (if any) that was paused by
- // the last play of this should now
- // await the resume event of the next-in-
- // line element on the "pause queue":
- if (pTmVlCurElementResumeEvent)
- {
- pTmVlPausedSiblResumesWhenCurElementEnds->
- m_idRef =
- pTmVlCurElementResumeEvent->m_idRef;
- break; // /We found both so we're done.
- }
- }
- }
- }
- }
- }
- else
- {
- curSMILTimelineStatus =
- SMILTimelineStatusFinishedPlaying;
- bTrackIsFinishedAndFrozen = FALSE;
- if (pTmpVal->m_pElement->m_ulRemoveTime > (ULONG32)lCurTime)
- {
- bTrackIsFinishedAndFrozen = TRUE;
- }
- }
- }
- }
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- const char* pCurStatus[7] =
- { "SMILTimelineStatusUnknown",
- "SMILTimelineStatusNeverScheduled",
- "SMILTimelineStatusStartScheduledForLater",
- "SMILTimelineStatusCurrentlyPlaying",
- "SMILTimelineStatusFinishedPlaying",
- "SMILTimelineStatusCurrentlyPaused",
- "SMILTimelineStatusCurrentlyPausedAndRestarting"
- };
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %st "
- "curSMILTimelineStatus==%s, ulActualStartTime=%lu, ulActualStopTime=%lu, "
- "lElementCurBeginTime=%ld, lEffectiveResolvedTime=%ld, "
- "lSyncbaseDelayAddedToResolvedTime=%ldn",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- pCurStatus[curSMILTimelineStatus],ulActualStartTime, ulActualStopTime,
- lElementCurBeginTime, lEffectiveResolvedTime,
- lSyncbaseDelayAddedToResolvedTime);
- ::fclose(f1);
- }
- #endif
- BOOL bIsInExcl = hasAncestor(SMILExcl, pTmpVal->m_pElement->m_pNode);
- // /If this is prior to playback, all elements in the list shuold be
- // descendants of an excl:
- if (bDoHandleExclBeforePlaybackStarts && !bIsInExcl)
- {
- continue;
- }
- // /Prior to playback, only add the first excl child that has a
- // begin time of 0s (or is the one with the earliest resolved begin):
- if (bIsInExcl && pExclChildAddedBeforePlayback &&
- pExclChildAddedBeforePlayback && pExclAncestor &&
- (*pExclChildAddedBeforePlayback)[(const char*)
- pExclAncestor->m_id])
- {
- HX_ASSERT(bDoHandleExclBeforePlaybackStarts);
- continue;
- }
- // /We should be in one of these four states; anything else means
- // there's an inconsistency somewhere:
- HX_ASSERT (SMILTimelineStatusUnknown != curSMILTimelineStatus);
- LONG32 lResolvedTimeToUse =
- lEffectiveResolvedTime-lSyncbaseDelayAddedToResolvedTime;
- // /Now, see if this pending time is ready to be used:
- if (lResolvedTimeToUse <= lCurTime ||
- // /OPTIMIZATION:
- // /If this element has never been scheduled, then go ahead
- // and schedule it with this newly-resolved (and possibly
- // future) time so core has greatest opportunity to pre-
- // buffer the element prior to commencing its playback:
- (!bIsInExcl &&
- SMILTimelineStatusNeverScheduled == curSMILTimelineStatus) ||
- // /OPTIMIZATION:
- // /If element is scheduled to play later and this new
- // begin time is prior to that, then use this new time
- // and give core a chance to buffer it in advance:
- (SMILTimelineStatusStartScheduledForLater ==
- curSMILTimelineStatus && lResolvedTimeToUse <
- lElementCurBeginTime) )
- {
- // Using the result, we need to decide what to do with
- // this element based on:
- // (1) If it has ever been added to the timeline,
- // (2) If it's currently playing, paused, or stopped,
- // (3) If its restart value is "always", "never", or
- // "whenNotActive"
- // Note: We don't want to just start the element based on a
- // newly-resolved begin time due to this event because
- // this element's begin list might be:
- // begin="foo.activate+5s; 10s"
- // so a click at 8s means the 10s begin will be next, not
- // the click-based begin that resolves to 13s.
- // /Handle all these cases, where 't' is a time unit and
- // "0t" is now (ulEventTime), 'rE' is resolved event time,
- // i.e., event time plus any offset, "psB" and "psE" are
- // previously-scheduled Begin and End times, respectively:
- //
- // (1) Has never played and is not yet scheduled to,
- // and resolved event time is negative, 0, or positive
- // offset from now:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+-----+-----+-----+
- // | /
- // rE
- //
- // (2) Has never played but is scheduled to later, and
- // resolved event time is prior to previously-scheduled
- // begin:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+-----+-====+====-+
- // | / | |
- // rE psB psE
- //
- // (3) Has never played but is scheduled to later, and
- // resolved event time is same as previously-scheduled
- // begin:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+--===+=====+==---+
- // | |
- // rE,psB psE
- //
- // (4) Has never played but is scheduled to later, and
- // resolved event time is after previously-scheduled
- // begin and prior to previously-scheduled end:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+--===+=====+====-+
- // | | |
- // psB rE psE
- //
- // (5) Has never played but is scheduled to later, and
- // resolved event time is same as previously-scheduled end:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+--===+=====+==---+
- // | |
- // psB psE,rE
- //
- // (6) Has never played but is scheduled to later, and
- // resolved event time is after previously-scheduled end:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-----+-----+-----+--===+====-+-----+
- // | | |
- // psB psE rE
- //
- // (7a) Is done playing, and resolved event time is negative,
- // 0, or positive offset from now, but not less than prior end:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-====+====-+-----+-----+-----+-----+
- // | | | /
- // psB psE rE
- //
- // (7b) Is done playing, and resolved event time is negative
- // offset from now and earlier than prior end:
- // -3t -2t -1t 0t 1t 2t 3t
- // +-====+====-+-----+-----+-----+-----+
- // | | |
- // psB rE psE
- //
- // (8) Is playing now, and resolved event time is prior to
- // previously-scheduled end time:
- // -3t -2t -1t 0t 1t 2t 3t
- // +---==+=====+=====+=====+==---+-----+
- // | | / |
- // psB rE psE
- //
- // (9) Is playing now, and resolved event time is same as
- // previously-scheduled end time:
- // -3t -2t -1t 0t 1t 2t 3t
- // +---==+=====+=====+=====+==---+-----+
- // | |
- // psB psE,rE
- //
- // (10) Is playing now, and resolved event time is after
- // previously-scheduled end time:
- // -3t -2t -1t 0t 1t 2t 3t
- // +---==+=====+=====+=====+==---+-----+
- // | | |
- // psB psE rE
- //
- //
- // Algorithm:
- // - Whenever an element becomes active (i.e., begins
- // playback), or whenever an element's begin time becomes
- // resolved, search its begin-time list for next resolved
- // time and, if restart != "never", add that to the
- // "watched element" list (in order by begin time), removing
- // any duplicate of that same element (with a later time).
- // - In every OnTimeSync(), check head of "watched element"
- // list and see if its time has been reached. If not,
- // ignore and keep going. If so, remove it and all other
- // elements in that list whose begin times have been reached
- // and decide whether or not to start/restart the element
- // based on restart value for that element.
- // /Do a clip-begin for any negative offset that was "clipped"
- // due to being resolved too late. We can calculate the
- // clip-begin offset as the difference between the effective
- // resolved time (when it actually begins) and the resolved-to
- // time (that includes the entire negative offset):
- INT32 lResolvedToTimeWithoutOffset =
- pTmpVal->getResolvedToTimeWithoutOffset();
- INT32 lEventTimeOffset = pTmpVal->getTimeOffset();
- INT32 lTimeWithFullOffset =
- lResolvedToTimeWithoutOffset + lEventTimeOffset;
- INT32 lClippedOffsetAmount =
- lTimeWithFullOffset - lEffectiveResolvedTime;
- INT32 lEffectiveEventTimeOffset =
- lEventTimeOffset - lClippedOffsetAmount;
- if (lEventTimeOffset < 0 && lClippedOffsetAmount < 0)
- {
- // /If clip-begin is invalid, set it otherwise add to it:
- pTmpVal->m_pElement->m_ulClipBegin = ((UINT32)-1 ==
- pTmpVal->m_pElement->m_ulAuthoredClipBegin?
- (ULONG32)(-lClippedOffsetAmount) :
- (ULONG32)(-lClippedOffsetAmount) +
- pTmpVal->m_pElement->m_ulAuthoredClipBegin);
- // /Set lEventTimeOffset to zero for call to setDelay,
- // below:
- lEventTimeOffset = 0;
- }
- BOOL bOKToKillExclSibling = FALSE;
- BOOL bAddTrack = FALSE;
- BOOL bPrepForRestartNeeded = FALSE;
- // /#define XXXEHODGE_DEBUG_CHECKPENDINGBEGINTIMES
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_CHECKPENDINGBEGINTIMES)
- { static BOOL bFirstTime = TRUE;
- FILE* f1 = ::fopen("c:\smil2_checkPending.txt", bFirstTime?"w":"a+");
- ::fprintf(f1, "npTmpVal->m_idRef= %s, LINE= %lu, "
- "curSMILTimelineStatus==SMILTimelineStatusCurrentlyPlaying?%lu, "
- "SmilRestartAlways==pTmpVal->m_pElement->m_restartBehavior%lu, "
- "lTimeWithFullOffset=%ld, lElementCurBeginTime=%ld, lEffectiveResolvedTime=%ld, "
- "lSyncbaseDelayAddedToResolvedTime=%ld, m_ulRemoveTime=%lun",
- (const char*)pTmpVal->m_idRef, (UINT32)__LINE__,
- curSMILTimelineStatus==SMILTimelineStatusCurrentlyPlaying,
- SmilRestartAlways==pTmpVal->m_pElement->m_restartBehavior,
- lTimeWithFullOffset, lElementCurBeginTime, lEffectiveResolvedTime,
- lSyncbaseDelayAddedToResolvedTime, lCurTime, pTmpVal->m_pElement->m_ulRemoveTime); ::fclose(f1);}
- #endif
- if (SMILTimelineStatusNeverScheduled == curSMILTimelineStatus)
- {
- bAddTrack = TRUE;
- bPrepForRestartNeeded = FALSE;
- bOKToKillExclSibling = TRUE;
- }
- // /Since we're starting earlier than when it's been scheduled,
- // restart doesn't come into play, but we have to insert that
- // future time into the pending begin time list:
- else if (SMILTimelineStatusStartScheduledForLater ==
- curSMILTimelineStatus)
- {
- // /XXXEH- OPTIMIZATION TODO: instead of
- // removeTrack+addTrack, just adjust time of
- // already-scheduled one:
- if (NULL == pTmpVal->m_pElement->m_pTimelineElement)
- {
- retval = HXR_UNEXPECTED;
- HX_ASSERT(pTmpVal->m_pElement->m_pTimelineElement);
- goto cleanup;
- }
- else
- {
- if (pTmpVal->m_pElement->m_pHandler ||
- bCurElementIsTimeContainer)
- {
- // /It's scheduled for later so it must have its
- // delay set:
- HX_ASSERT((UINT32)-1 !=
- pTmpVal->m_pElement->m_ulDelay);
- LONG32 lOldScheduledBegin =
- lElementCurBeginTime;
- // /XXXEH- OPTIMIZATION TODO: if
- // (SMILTimelineStatusStartScheduledForLater ==
- // curSMILTimelineStatus) then we should not remove
- // and then add the track back, but rather should
- // just call begin on the track now. This requires,
- // however, that all datatypes can handle having
- // their time offsets adjusted on the fly:
- // /See if pID is a time container; if so, call
- // handleTrackRemoval() on all its descendant media:
- if (bCurElementIsTimeContainer)
- {
- retval = HXR_OK;
- SMILNode* pChild = pTmpVal->m_pElement->
- m_pNode->getFirstChild();
- while (pChild)
- {
- CSmilElement* pElement = pChild->m_pElement;
- if (pElement && pElement->m_pHandler &&
- pElement->m_bInsertedIntoTimeline)
- {
- HX_RESULT retval2 = pElement->m_pHandler->
- handleTrackRemoval((const char*)
- pElement->m_pNode->m_id,
- (INT32)pElement->m_pNode->m_nGroup);
- if (HXR_OK == retval2)
- {
- // /The duration changed due to an
- // event, not due to clipping by
- // our sync-parent. Set this to
- // false so elementResolved() will
- // allow sync-arcs to resolve on
- // our new end:
- pElement->m_bCurEndClippedByParent =
- FALSE;
- // /Fixes case where element has
- // sync arc to this end time and
- // we need to notify it that
- // we've ended early:
- m_pTimelineElementManager->notify((const char*) pElement->m_pNode->m_id);
- }
- }
- pChild = pTmpVal->m_pElement->m_pNode->
- getNextChild();
- }
- }
- else
- {
- retval = pTmpVal->m_pElement->m_pHandler->
- handleTrackRemoval(
- (const char*)pTmpVal->
- m_pElement->m_pNode->m_id,
- (INT32)pTmpVal->
- m_pElement->m_pNode->m_nGroup);
- }
- if (HXR_OK == retval)
- {
- // /The duration changed due to an event, not due
- // to clipping by our sync-parent. Set this to
- // false so elementResolved() will allow
- // sync-arcs to resolve on our new end:
- pTmpVal->m_pElement->m_bCurEndClippedByParent =
- FALSE;
- // /Fixes case where element has a sync arc to
- // this end time and we need to notify it that
- // we've ended early:
- m_pTimelineElementManager->notify((const char*) pTmpVal->m_pElement->m_pNode->m_id);
- // /Place previously-scheduled future time into
- // pending-time list since it's been superseded
- // by pTmpVal:
- retval = insertElementWithPendingBeginOrEnd(
- pTmpVal->m_pElement, lOldScheduledBegin,
- SmilBeginTimeList);
- }
- }
- else
- {
- // XXXMEH - removed since we sometimes get multiple
- // char events, before the events have even been
- // processed.
- // HX_ASSERT(pTmpVal->m_pElement->m_pHandler);
- retval = HXR_UNEXPECTED;
- }
- }
- bAddTrack = TRUE;
- bPrepForRestartNeeded = TRUE;
- bOKToKillExclSibling = TRUE;
- }
- // /If we're playing now and restart is "always" and our new
- // begin time is not in the future and is not so far in the
- // past that it was earlier than the currently-playing time,
- // OR if we're done playing and restart is not "never", then
- // remove the track and add it back with new begin/end time:
- else if (((SMILTimelineStatusCurrentlyPlaying ==
- curSMILTimelineStatus ||
- // /Part of fix for PR 62397:
- SMILTimelineStatusCurrentlyPausedAndRestarting ==
- curSMILTimelineStatus) &&
- SmilRestartAlways ==
- pTmpVal->m_pElement->m_restartBehavior &&
- (lTimeWithFullOffset >=
- lElementCurBeginTime &&
- lEffectiveResolvedTime <= lCurTime)) ||
- (SMILTimelineStatusFinishedPlaying ==
- curSMILTimelineStatus && SmilRestartNever !=
- pTmpVal->m_pElement->m_restartBehavior) )
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG)
- {FILE* f1 = ::fopen("c:\smil2.txt", "a+"); ::fprintf(f1, "npTmpVal->m_idRef= %s, LINE= %lun", (const char*)pTmpVal->m_idRef, (UINT32)__LINE__); ::fclose(f1);}
- #endif
- // /If we're finished playing, handle killing an excl
- // sibling that's active, if any. (Note: if we're not
- // finished playing, then we are the active one so no
- // need to shut anyone else down):
- // (..but note: we're not the active one if we're paused)
- if (SMILTimelineStatusFinishedPlaying ==
- curSMILTimelineStatus)
- {
- bOKToKillExclSibling = TRUE;
- }
- // /Last part of fix for PR 62397:
- else if (SMILTimelineStatusCurrentlyPausedAndRestarting ==
- curSMILTimelineStatus &&
- !pTmpVal->isResumeEvent())
- {
- bOKToKillExclSibling = TRUE;
- }
- // /XXXEH- OPTIMIZATION TODO(?): instead of
- // removeTrack+addTrack, just adjust time of
- // already-playing one (?):
- if (NULL == pTmpVal->m_pElement->m_pTimelineElement)
- {
- retval = HXR_UNEXPECTED;
- HX_ASSERT(pTmpVal->m_pElement->m_pTimelineElement);
- goto cleanup;
- }
- else
- {
- if ((pTmpVal->m_pElement->m_pHandler ||
- bCurElementIsTimeContainer) &&
- // /(for PR 62688 and others): don't remove
- // track(s) that are done playing:
- (SMILTimelineStatusFinishedPlaying !=
- curSMILTimelineStatus ||
- // /Fixes PR 66212, which broke when PR 62688
- // fix, above, was added: we do need to remove a
- // track that is finished but *frozen* (and
- // thus track/renderer is still open):
- bTrackIsFinishedAndFrozen) )
- {
- // /See if pID is a time container; if so, call
- // handleTrackRemoval() on all its descendant media:
- if (bCurElementIsTimeContainer)
- {
- retval = HXR_OK;
- SMILNode* pChild = pTmpVal->m_pElement->
- m_pNode->getFirstChild();
- while (pChild)
- {
- CSmilElement* pElement = pChild->m_pElement;
- if (pElement && pElement->m_pHandler &&
- pElement->m_bInsertedIntoTimeline)
- {
- HX_RESULT retval2 = pElement->m_pHandler->
- handleTrackRemoval((const char*)
- pElement->m_pNode->m_id,
- (INT32)pElement->m_pNode->m_nGroup);
- if (HXR_OK == retval2)
- {
- // /The duration changed due to an
- // event, not due to clipping by
- // our sync-parent. Set this to
- // false so elementResolved() will
- // allow sync-arcs to resolve on
- // our new end:
- pElement->m_bCurEndClippedByParent =
- FALSE;
- // /Fixes case where element has
- // sync arc to this end time and
- // we need to notify it that
- // we've ended early:
- m_pTimelineElementManager->notify((const char*) pElement->m_pNode->m_id);
- }
- }
- pChild = pTmpVal->m_pElement->m_pNode->
- getNextChild();
- }
- }
- else
- {
- retval = pTmpVal->m_pElement->m_pHandler->
- handleTrackRemoval(
- (const char*)pTmpVal->
- m_pElement->m_pNode->m_id,
- (INT32)pTmpVal->
- m_pElement->m_pNode->m_nGroup);
- }
- // /Fixes case where element has a sync arc to this
- // end time and we need to notify it that we've
- // ended early:
- if (HXR_OK == retval)
- {
- // /The duration changed due to an event, not due
- // to clipping by our sync-parent. Set this to
- // false so elementResolved() will allow
- // sync-arcs to resolve on our new end:
- pTmpVal->m_pElement->m_bCurEndClippedByParent =
- FALSE;
- m_pTimelineElementManager->notify((const char*) pTmpVal->m_pElement->m_pNode->m_id);
- }
- retval = HXR_OK;
- bAddTrack = TRUE;
- bPrepForRestartNeeded = TRUE;
- }
- // /Fixes elements-won't-restart-in-excl bug introduced by
- // initial PR 62688 fix; if it's done playing, allow it to
- // restart even though we didn't (have to) remove it, above:
- else if (SMILTimelineStatusFinishedPlaying ==
- curSMILTimelineStatus)
- {
- retval = HXR_OK;
- bAddTrack = TRUE;
- bPrepForRestartNeeded = TRUE;
- }
- else
- {
- // XXXMEH - removed since we sometimes get multiple
- // char events, before the events have even been
- // processed.
- // HX_ASSERT(pTmpVal->m_pElement->m_pHandler);
- retval = HXR_UNEXPECTED;
- }
- }
- }
- BOOL bTimeValWasDeferred = FALSE;
- if (bOKToKillExclSibling)
- {
- // /This finds the first actively-playing media element of
- // the excl (if there even is an excl), noting that there may
- // be more than one media element playing in the case where
- // they are all children of a par descendant of the excl:
- SMILNode* pActiveSibling = findActiveChildOfAncestorExcl(
- pTmpVal->m_pElement->m_pNode, lCurTime);
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %s, "
- "findActiveChildOfAncestorExcl() found: pActiveSibling id=%s n",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id, pActiveSibling?
- (const char*)pActiveSibling->m_id:"NULL");
- ::fclose(f1);
- }
- #endif
- if (pActiveSibling)
- {
- // /Is currently playing (unless it was stopped
- // already by someone else) so kill it:
- if (NULL != pActiveSibling->m_pElement->m_pHandler)
- {
- SMILPriorityClassPeersHigherLowerVal interruptAction=
- SMILPriorityClassStop;
- SMILPriorityClassPauseDisplay
- activeSiblingPauseDisplay =
- SMILPriorityClassPauseDisplayShow;
- // /Decide based on priorityClass values what to do
- // here; e.g., if this is a peer of the new media that
- // wants to play, then the peers value will determine
- // whether we stop, pause, or do nothing to it:
- SMILNode* pPriorityClassOfActiveSibling =
- getSpecificAncestor(SMILPriorityClass,
- pActiveSibling);
- if (pPriorityClassOfActiveSibling)
- {
- // /Find priorityClass of interrupting media:
- SMILNode* pPriorityClassOfInterrupter =
- getSpecificAncestor(SMILPriorityClass,
- pTmpVal->m_pElement->m_pNode);
- HX_ASSERT(pPriorityClassOfInterrupter);
- if (!pPriorityClassOfInterrupter ||
- !pPriorityClassOfInterrupter->m_pElement)
- {
- // /XXXEH- fire off this error: all media in
- // an excl must be inside a priorityClass if
- // *any* other media in that excl is inside
- // a priorityClass:
- break;
- }
- CSmilPriorityClassElement* pPCActiveElem =
- (CSmilPriorityClassElement*)
- pPriorityClassOfActiveSibling->m_pElement;
- HX_ASSERT(pPCActiveElem);
- activeSiblingPauseDisplay =
- pPCActiveElem->m_pauseDisplay;
- // /If they have the same priorityClass, then
- // look at the peers behavior to see what to do:
- if (pPriorityClassOfInterrupter ==
- pPriorityClassOfActiveSibling)
- {
- interruptAction = pPCActiveElem->m_peers;
- }
- // /Else, if interrupting p.c. is higher (i.e.,
- // declared (lexically) earlier in the excl),
- // look at active p.c.'s "higher" val:
- else if (pPriorityClassOfInterrupter->
- m_ulTagStartLine <
- pPriorityClassOfActiveSibling->
- m_ulTagStartLine ||
- (pPriorityClassOfInterrupter->
- m_ulTagStartLine ==
- pPriorityClassOfActiveSibling->
- m_ulTagStartLine &&
- pPriorityClassOfInterrupter->
- m_ulTagStartColumn <
- pPriorityClassOfActiveSibling->
- m_ulTagStartColumn) )
- {
- interruptAction = pPCActiveElem->m_higher;
- }
- // /Else, if interrupting p.c. is lower (i.e.,
- // declared (lexically) later in the excl), look
- // at active p.c.'s "lower" val:
- else
- {
- interruptAction = pPCActiveElem->m_lower;
- }
- }
- // /This is active node's "syncbase" element
- // which may itself be a child of this excl:
- SMILNode* pTimelineParentOfActiveSibling =
- getSyncAncestor(pActiveSibling);
- HX_ASSERT(pTimelineParentOfActiveSibling);
- // /Is needed to fix PR 57120 (wrapping par version);
- // in case of a deferral, it's the *interruptor* that
- // defers, not the active sibling (unlike with pause):
- SMILNode* pTimelineParentOfInterruptor =
- getSyncAncestor(pTmpVal->m_pElement->m_pNode);
- HX_ASSERT(pTimelineParentOfInterruptor);
- // /Here's where we need to reset m_bIsDeferredInExcl
- // to FALSE if a deferred element is now getting a
- // chance to play (and not be further deferred):
- if (pTmpVal->m_pElement->m_bIsDeferredInExcl &&
- interruptAction !=SMILPriorityClassDefer)
- {
- pTmpVal->m_pElement->m_bIsDeferredInExcl = FALSE;
- pTmpVal->m_pElement->m_ulTimeDeferralOccurred = (UINT32)-1;
- }
- switch (interruptAction)
- {
- case SMILPriorityClassPause:
- {
- do
- {
- if (SMILPriorityClassPauseDisplayHide ==
- activeSiblingPauseDisplay)
- {
- // /There are some cases where this
- // might be NULL, but we shouldn't
- // get to this part of this function
- // if it's NULL:
- HX_ASSERT(pPauseDisplayHideElementList);
- if (pPauseDisplayHideElementList)
- {
- CHXString* pCStr = new CHXString;
- if (pCStr)
- {
- // /copy it over:
- *pCStr = (const char*)
- pActiveSibling->m_id;
- pPauseDisplayHideElementList->
- AddTail(pCStr);
- }
- }
- }
- else if (SMILPriorityClassPauseDisplayDisable ==
- activeSiblingPauseDisplay)
- {
- // /There are some cases where this
- // might be NULL, but we shouldn't
- // get to this part of this function
- // if it's NULL:
- HX_ASSERT(pPauseDisplayDisableElementList);
- if (pPauseDisplayDisableElementList)
- {
- CHXString* pCStr = new CHXString;
- if (pCStr)
- {
- // /copy it over:
- *pCStr = (const char*)
- pActiveSibling->m_id;
- pPauseDisplayDisableElementList->
- AddTail(pCStr);
- }
- }
- }
- LONG32 lDiffBetwnNowAndBegin =
- lCurTime-lEffectiveResolvedTime;
- if (0==lEffectiveResolvedTime &&
- lDiffBetwnNowAndBegin<=10)
- {
- // /Fixes SMIL 2.0 Interop Timing #13.15:
- // allow first track to draw once by
- // interrupting in a subsequent call to
- // checkPending...():
- bTimeValWasDeferred = TRUE;
- goto doneWithRestartCode;
- }
- HX_ASSERT(lDiffBetwnNowAndBegin>0);
- if (lDiffBetwnNowAndBegin > 0)
- {
- // /XXXEH- TODO: if and when
- // we stop treating scheduled
- // interrupts as events, this
- // will fire off and we'll need to
- // delay the subsequent pause, below:
- HX_ASSERT(lDiffBetwnNowAndBegin<500);
- }
- // /Adding this block helps fix PR 86107.
- // We need to adjust the duration of this
- // element to reflect the anticipated time
- // it will be paused. That allows other
- // elements that play after it ends to
- // adjust accordingly before it's too late:
- // /Adding the if() around the block helps
- // fix PR 100601 & PR 85896 (=PR 79288):
- // /BUT, don't do this if duration of pauser
- // isn't resolved:
- // [XXXEH- we may need to set up a resolve-
- // this-when-trackDurationSet-callback-
- // happens construct (as is done in
- // elementResolved()) and do the following
- // then, when duration becomes resolved,
- // but I can't create content that breaks
- // without that]:
- if ((UINT32)-1 !=
- pTmpVal->m_pElement->m_ulDuration)
- {
- pActiveSibling->m_pElement->
- m_ulAnticipatedPauseDur =
- pTmpVal->m_pElement->m_ulDuration;
- ULONG32 ulAnticipatedDurInclPause =
- pActiveSibling->m_pElement->
- m_ulAnticipatedPauseDur +
- pActiveSibling->m_pElement->
- m_ulDuration;
- if (pActiveSibling->m_pElement->
- m_ulAnticipatedPauseDur >=
- WAY_IN_THE_FUTURE ||
- pActiveSibling->m_pElement->
- m_ulDuration >=
- WAY_IN_THE_FUTURE)
- {
- ulAnticipatedDurInclPause =
- WAY_IN_THE_FUTURE -
- // /Helps fix PR 100601 and
- // PR 85896 (=PR 79288):
- // /Subtract delay so total
- // reported to core doesn't
- // exceed indef "magic number":
- pActiveSibling->m_pElement->m_ulDelay;
- }
- durationResolved((const char*)
- pActiveSibling->m_pElement->
- m_pNode->m_id,
- ulAnticipatedDurInclPause,
- FALSE /* not being set by parent */,
- TRUE /* dur is pause extending */);
- // /Force smildocrender to HandleElements():
- bREFSomeScheduleWasChanged = TRUE;
- } // /End block added to help fix PR 86107.
- // /This method not only pauses the
- // element but also creates a new
- // SmilTimeValue and inserts it in the
- // pending begin time list; this new
- // time value watches for the
- // iterrupting media to finish:
- SmilTimeValue* pReturnedTimeVal = NULL;
- retval = pActiveSibling->m_pElement->
- m_pHandler->handleTrackPausing(
- pActiveSibling,
- lEffectiveResolvedTime,
- activeSiblingPauseDisplay,
- pTmpVal->m_pElement->m_pNode->m_id);
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "At %6ld: timeVal's id = %s, "
- "handleTrackPausing(%s) returned: 0x%08xn",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- (const char*)pActiveSibling->m_id, retval);
- ::fclose(f1);