smlparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:879k
- }
- #endif
- HX_ASSERT(HXR_OK == retval);
- // /Helps fix PR 53531: this will prevent
- // this one from being seen as the current
- // "active" sibling if another excl track
- // gets added while this one is paused; it
- // also resets some vars to prolong its
- // existence during pause past its original
- // end time if that end is not explicit:
- if (HXR_OK == retval)
- {
- pActiveSibling->m_pElement->
- prepForPauseInExcl(
- lEffectiveResolvedTime);
- }
- if (pTimelineParentOfActiveSibling &&
- SMILExcl !=
- pTimelineParentOfActiveSibling->m_tag)
- {
- // /Find next timeline sibling:
- do
- {
- pActiveSibling = findNextSibling(
- pActiveSibling);
- } while (pActiveSibling &&
- // /XXXEH- TODO: handle deeper
- // nesting of timed objects:
- !isMediaObject(pActiveSibling));
- }
- else // /No parent par or seq:
- {
- break;
- }
- } while (pActiveSibling);
- }
- break;
- case SMILPriorityClassDefer:
- {
- // /XXXEH- TODO: determine if there is more
- // than one currently-playing track:
- // /We need to set the begin time of the
- // would-be interrupter to that of the
- // currently-playing one(s); if there is
- // more than one media track playing (in a
- // par) then we want to defer until the
- // end of the par:
- SMILNode* pDeferUntilAfterThisNode = pActiveSibling;
- // /To fix PR 85885 where multiple clips get
- // deferred while first sibling plays, we need
- // to defer the second-deferred one to after
- // its deferred sibling ends, not to after the
- // first one ends:
- SMILNode* pLastDeferredInSameExcl =
- findLastDeferredChildOfAncestorExcl(
- pTmpVal->m_pElement->m_pNode, lCurTime);
- ULONG32 ulNewStartTime = pDeferUntilAfterThisNode->
- m_pElement->m_ulDuration +
- pDeferUntilAfterThisNode->m_pElement->m_ulDelay;
- // /Fixes PR 69638: active sib's duration can
- // include its delay so end is not always
- // dur+delay; getCurrent...() handles this:
- ULONG32 ulTotalDelay = 0;
- if (HXR_OK == pDeferUntilAfterThisNode->m_pElement->
- getCurrentScheduledStopTime(ulTotalDelay))
- {
- ulNewStartTime = ulTotalDelay;
- }
- else
- {
- HX_ASSERT(0); // /getCurrent...() failed!
- }
- // /lEffectiveResolvedTime is our current begin
- // time, so we need to add the difference;
- INT32 lDiff = (INT32)ulNewStartTime -
- lEffectiveResolvedTime;
- // /For PR 85885, just set defer-to time to indef and
- // await endEvent of prior-in-queue deferred element:
- if (pLastDeferredInSameExcl)
- {
- HX_ASSERT(1); // /debug only.
- pDeferUntilAfterThisNode = pLastDeferredInSameExcl;
- ulNewStartTime = SMILTIME_DEFERRED_INDEFINITELY;
- // /Helps fix PR 85885:
- // /Ceate a new SmilTimeValue watching for
- // "undeferEvent" on prior-in-defer-queue element;
- SmilTimeValue* pNewTimeVal =
- new SmilTimeValue(m_pContext,
- /* start line don't care:*/ 0,
- pTmpVal->m_pElement);
- HX_ASSERT(pNewTimeVal);
- if(pNewTimeVal)
- {
- CHXString pStr =
- pLastDeferredInSameExcl->m_id;
- pStr += ".undeferEvent";
- HX_RESULT pnr1 = pNewTimeVal->parseValue(
- pStr, SMILSyncAttrBegin,
- (const char*)
- pTmpVal->m_pElement->m_pNode->m_id);
- // /Note: this function gets rid of any
- // existing resumeEvent on this element
- // since it can only be in the "defer
- // stack" once:
- BOOL bOldUndeferEventWasRemoved = FALSE;
- HX_RESULT rslt = addUndeferEvent(
- pNewTimeVal,
- bOldUndeferEventWasRemoved);
- }
- }
- // /If par in excl is deferring, then mark it
- // as such so it won't be seen as
- // "currently playing" next time:
- if (pTimelineParentOfInterruptor &&
- SMILExcl !=
- pTimelineParentOfInterruptor->m_tag &&
- pTimelineParentOfInterruptor->m_pElement)
- {
- pTimelineParentOfInterruptor->m_pElement->
- prepForDeferralInExcl((UINT32)lCurTime);
- }
- // /This is needed to fix PR 57120; it's the
- // *interruptor* that defers, not the active
- // sibling (unlike with pause):
- pTmpVal->m_pElement->prepForDeferralInExcl((UINT32)lCurTime);
- HX_ASSERT(lDiff >=
- FUDGE_FACTOR_WHEN_DEFERRING_PAST_END_OF_GROUP);
- if (lDiff >
- FUDGE_FACTOR_WHEN_DEFERRING_PAST_END_OF_GROUP)
- {
- // /Only handle this by the early fudge
- // factor if needed; if presentation is
- // already long enough, no need to do this:
- UINT32 ulCurGroupDuration = 0;
- pActiveSibling->m_pElement->m_pHandler->
- GetCurGroupDuration(ulCurGroupDuration);
- if (ulNewStartTime +
- FUDGE_FACTOR_FOR_DEFERRING_PRIOR_TO_END_OF_GROUP
- >= ulCurGroupDuration &&
- SMILTIME_DEFERRED_INDEFINITELY !=
- ulNewStartTime &&
- // /If it's 0, then presentation dur
- // is unresolved (indefinite):
- ulCurGroupDuration !=0)
- {
- // /Fixes Interop Timing #25.6:
- // Subtract fudge factor so this has a
- // chance to begin before player stops:
- ulNewStartTime -=
- FUDGE_FACTOR_WHEN_DEFERRING_PAST_END_OF_GROUP;
- }
- else if (SMILTIME_DEFERRED_INDEFINITELY !=
- ulNewStartTime)
- {
- // /To fix PR 69671, we *add* fudge
- // factor so any track that gets paused
- // by the active one can resume before
- // this deferred (lower) tries to begin:
- ulNewStartTime +=
- FUDGE_FACTOR_FOR_DEFERRING_PRIOR_TO_END_OF_GROUP;
- }
- if (pTmpVal->deferUntil(
- (INT32)ulNewStartTime))
- {
- bTimeValWasDeferred = TRUE;
- bAddTrack = FALSE;
- }
- }
- }
- break;
- case SMILPriorityClassNever:
- {
- ; // /Don't need to do diddly, and we should
- // prevent the new track from playing:
- bAddTrack = FALSE;
- bREFSomeScheduleWasChanged = FALSE;
- }
- break;
- case SMILPriorityClassStop:
- default:
- {
- #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, pActiveSibling id=%s, "
- "bPrepForRestartNeeded=%lu n",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- (const char*)pActiveSibling->m_id, (UINT32)bPrepForRestartNeeded);
- ::fclose(f1);
- }
- #endif
- // /Helps fix PR 56053: if par in excl is
- // stopping, then mark it as such so it won't
- // be seen as "currently playing" next time:
- if (pTimelineParentOfActiveSibling &&
- SMILExcl !=
- pTimelineParentOfActiveSibling->m_tag &&
- pTimelineParentOfActiveSibling->m_pElement)
- {
- pTimelineParentOfActiveSibling->m_pElement->
- prepForStopInExcl(lCurTime);
- }
- do
- {
- retval = pActiveSibling->m_pElement->
- m_pHandler->handleTrackRemoval(
- (const char*)pActiveSibling->m_id,
- (INT32)pActiveSibling->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, pActiveSibling id=%s, "
- "handleTrackRemoval() retval=0x%08x n",
- lCurTime, (const char*)pTmpVal->m_pElement->m_pNode->m_id,
- (const char*)pActiveSibling->m_id, retval);
- ::fclose(f1);
- }
- #endif
- // /Helps fix PR 56053: if child in excl
- // is stopping, then mark it as such so
- // it won't be seen as "currently
- // playing" next time:
- pActiveSibling->m_pElement->
- prepForStopInExcl(lCurTime);
- // /Needed for where element has a sync
- // arc to this end time and we need to
- // notify it that it has ended early:
- if (HXR_OK == retval)
- {
- // /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*) pActiveSibling->m_id);
- }
- if (pTimelineParentOfActiveSibling &&
- SMILExcl !=
- pTimelineParentOfActiveSibling->m_tag)
- {
- // /Find next timeline sibling:
- do
- {
- pActiveSibling = findNextSibling(
- pActiveSibling);
- } while (pActiveSibling &&
- // /XXXEH- TODO: handle deeper
- // nesting of timed objects:
- !isMediaObject(pActiveSibling));
- }
- else // /No parent par or seq:
- {
- break;
- }
- } while (pActiveSibling);
- bREFSomeScheduleWasChanged = TRUE;
- }
- break;
- }
- }
- }
- }
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG)
- {FILE* f1 = ::fopen("c:\smil2.txt", "a+"); ::fprintf(f1, "npTmpVal->m_idRef= %s, bAddTrack= %lun", (const char*)pTmpVal->m_idRef, (UINT32)bAddTrack); ::fclose(f1);}
- #endif
- if (bAddTrack)
- {
- // /We should never add a track that was deferred:
- HX_ASSERT(!bTimeValWasDeferred);
- // /Start the element @ NOW+offset by inserting into the
- // timeline (via setDelay()) and adding track (via
- // handleNextElement())
- // /First, see if there is a resolved end time
- // that's after this begin time, that might affect the dur;
- // if not, then play until its syncBase ends if
- // it is restarting, otherwise just use its originalDur:
- SmilTimeValue* pNextResolvedEndTimeValue = NULL;
- HX_RESULT rettimeval = HXR_OK;
- rettimeval = pTmpVal->m_pElement->getNextResolvedTimeValue(
- pNextResolvedEndTimeValue,
- // /Use this since we're not sure what group time is:
- SMILTIME_NEGATIVE_INFINITY,
- lEffectiveResolvedTime,
- SmilEndTimeList,
- /* Don't need list of resolved times:*/ NULL);
- LONG32 lNextResolvedEndTime;
- HX_RESULT rtvalx = HXR_FAIL;
- if (SUCCEEDED(rettimeval) &&
- NULL != pNextResolvedEndTimeValue)
- {
- rtvalx = pNextResolvedEndTimeValue->
- getEffectiveResolvedTime(
- lNextResolvedEndTime);
- }
- // /Fixes PR 50589: check for toggle behavior if
- // begin and end times are the same and pTmpVal has same
- // timeValue values as pNextResolvedEndTimeValue, then
- // mark pNextResolvedEndTimeValue so it won't be used as an
- // end time, and get next-next resolved end
- if (HXR_OK == rtvalx &&
- lEffectiveResolvedTime == lNextResolvedEndTime &&
- pNextResolvedEndTimeValue &&
- pTmpVal->isSameTimeValue(pNextResolvedEndTimeValue))
- {
- pTimeValEndToggleToBeIgnored =
- pNextResolvedEndTimeValue;
- // /Get next one:
- rettimeval =
- pTmpVal->m_pElement->getNextResolvedTimeValue(
- pNextResolvedEndTimeValue,
- // /Use this since we're not sure what group time is:
- SMILTIME_NEGATIVE_INFINITY,
- lEffectiveResolvedTime + 1, SmilEndTimeList,
- /* Don't need list of resolved times:*/ NULL);
- }
- BOOL bHasFutureResolvedEnd = FALSE;
- // /In case we're restarting, we need to either have an
- // explicit dur or a future end that's either in the future
- // because it's unresolved or is resolved to a future time:
- // If it's playing for the first time, then it has a default
- // dur/end in lieu of an explicit one:
- BOOL bIsntRestartingOrHasExplicitDurOrFutureEnd =
- !bPrepForRestartNeeded;
- if (SUCCEEDED(rettimeval) &&
- NULL != pNextResolvedEndTimeValue)
- {
- HX_RESULT rtval = pNextResolvedEndTimeValue->
- getEffectiveResolvedTime(
- lNextResolvedEndTime);
- if (SUCCEEDED(rtval))
- {
- bHasFutureResolvedEnd = TRUE;
- bIsntRestartingOrHasExplicitDurOrFutureEnd = TRUE;
- }
- }
- ULONG32 ulNewDuration = (bPrepForRestartNeeded?
- (UINT32)-1:
- pTmpVal->m_pElement->m_ulOriginalDuration);
- BOOL bHasExplicitValidDur = FALSE;
- // /If has explicitly authored simple dur, use it instead:
- if (pTmpVal->m_pElement->m_bHasExplicitDur &&
- (UINT32)-1 != pTmpVal->m_pElement->m_ulAuthoredDur)
- {
- bHasExplicitValidDur = TRUE;
- ulNewDuration = pTmpVal->m_pElement->m_ulAuthoredDur;
- bIsntRestartingOrHasExplicitDurOrFutureEnd = TRUE;
- }
- SMILNode* pSyncNode = NULL;
- if (bHasFutureResolvedEnd)
- {
- HX_ASSERT(lEffectiveResolvedTime < lNextResolvedEndTime);
- // /We need to use the new end time and ignore the
- // m_ulOriginalDuration:
- if (lEffectiveResolvedTime < lNextResolvedEndTime)
- {
- ulNewDuration = (UINT32)(lNextResolvedEndTime -
- lEffectiveResolvedTime);
- }
- }
- // /If not restarting and has no future end time and has no
- // explcitly-authored dur, and has an explicit end time that
- // is now or in the past, then don't insert this.
- // Fixes SMIL 2.0 Interop Timing #18.8 endsync_first_par5_RM:
- else if (!bPrepForRestartNeeded && !bHasExplicitValidDur &&
- (pTmpVal->m_pElement->m_bHasExplicitEnd &&
- // /Need to make sure explicit end is in the past:
- pTmpVal->m_pElement->m_lEndOffset <= lCurTime) &&
- // /Allow for begin="[some event]" end="indefinite":
- !pTmpVal->m_pElement->m_bIndefiniteEnd &&
- // /Adding this check helps fix PR 52006: if there is an
- // end value that is not yet resolved, we want to treat
- // its end as indefinite which is a valid future end time:
- !pTmpVal->m_pElement->hasUnresolvedEndTime())
- {
- goto doneWithRestartCode;
- }
- // /First, see if we need to look for a future unresolved end
- // in case we're restarting, have no explicit dur, and have
- // an explicit end but none that's in the future. According
- // to "getNextInterval" in the SMIL 2.0 Timing draft, we
- // should restart only in this case if there's an event-based
- // end:
- if (!bIsntRestartingOrHasExplicitDurOrFutureEnd)
- {
- if (!pTmpVal->m_pElement->m_bHasExplicitDur &&
- !pTmpVal->m_pElement->m_bHasExplicitEnd)
- {
- bIsntRestartingOrHasExplicitDurOrFutureEnd = TRUE;
- }
- else if (pTmpVal->m_pElement->hasUnresolvedEndTime())
- {
- bIsntRestartingOrHasExplicitDurOrFutureEnd = TRUE;
- }
- }
- // /We shouldn't restart because we're beyond our end time(s)
- if (!bIsntRestartingOrHasExplicitDurOrFutureEnd)
- {
- // /XXXEH- How do we handle the following at 10s?:
- // <par begin="0s;10s" end="5s" endsync="last">,,,</par>.
- // It has no valid end after 10s, but it does have an
- // endsync and the SMIL 2.0 Timing draft doesn't say if
- // that counts like a dur would have.
- goto doneWithRestartCode;
- }
- // /This is needed for PR 63650 fix:
- ULONG32 ulMaxDuration = (UINT32)-1;
- // /This is needed to keep us from extending past our
- // sync-base's end, (if there is an explicit end):
- pSyncNode = getSyncAncestor(pTmpVal->m_pElement->m_pNode);
- ULONG32 ulMaxEndTime = (UINT32)-1;
- if (pSyncNode && pSyncNode->m_pElement)
- {
- ULONG32 ulSyncBaseDuration = (UINT32)-1;
- ULONG32 ulSyncBaseDelay = 0;
- if ((UINT32)-1 != pSyncNode->m_pElement->m_ulDelay)
- {
- ulSyncBaseDelay =
- pSyncNode->m_pElement->m_ulDelay;
- }
- if ((UINT32)-1 != pSyncNode->m_pElement->m_ulDuration
- && pSyncNode->m_pElement->
- m_pTimelineElement->durationSet())
- {
- ulSyncBaseDuration =
- pSyncNode->m_pElement->m_ulDuration;
- }
- // /For final PR 62688 fix (par & excl versions):
- BOOL bEndsyncIsAllAndAllAreDone =
- pSyncNode->m_pElement->m_nEndsyncEventSourceTag ==
- SMILEventSourceAll &&
- pSyncNode->m_pElement->m_pTimelineElement->
- getNumChildren() >=
- pSyncNode->m_pElement->m_pTimelineElement->
- numChildDursAdded() &&
- // /Helps fix PR 62408 and PR 50660; if endsync="all" and
- // all children have weighed in, we still need to allow
- // children to restart before parent has ended:
- // Note: PR 62688 is still fixed with this change:
- lEffectiveResolvedTime >
- ulSyncBaseDelay+ulSyncBaseDuration;
- // /Calculate the end time constraints, if any,
- // imposed by syncBase:
- // /XXXEH- check delay constraints as well? I think
- // that's already handled in setDelay:
- if ((UINT32)-1 != ulSyncBaseDuration &&
- // /All this logic fixes restarting of element
- // when parent does *not* have an explicit dur
- // or end and thus its dur or end can be extended
- // (but wasn't being extended due to maxEndTime
- // begin set here):
- (pSyncNode->m_pElement->m_bHasExplicitDur ||
- pSyncNode->m_pElement->m_bHasExplicitEnd ||
- // /Final(?) fix for PR 62688 (par & excl
- // versions): endsync="all" also should constrain
- // if it has fully resolved:
- bEndsyncIsAllAndAllAreDone ||
- // /Or it has a (resolved) endsync=first:
- (pSyncNode->m_pElement->m_nEndsyncEventSourceTag ==
- SMILEventSourceFirst) ||
- // /Or it has an (resolved) endsycn=[some ID]:
- (pSyncNode->m_pElement->m_nEndsyncEventSourceTag ==
- SMILEventSourceID) ) )
- {
- ulMaxEndTime = ulSyncBaseDelay + ulSyncBaseDuration;
- #if 1 /* XXXEH- this works with PR 59584 and PR 62688 but needs more testing: */
- if (pSyncNode->m_pElement->
- m_bDurationIncludesDelayBeyondSyncbase)
- {
- // /Fixes PR 56686 case 1 where click extends parent's
- // set duration:
- ulMaxEndTime -= pSyncNode->m_pElement->
- m_ulBeginOffsetFromSyncBase;
- }
- #else /* XXXEH- remove this when above code is better tested: */
- ulDelayBeyondSyncBase = ulChildDelayBeyondStartOfThis;
- // /This fixes case where excl has begin offset and child does too:
- // I'm unsure if this works under all conditions, thus the assert:
- if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
- {
- if (!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
- {
- ulDelayBeyondSyncBase +=
- m_pSourceElement->m_ulBeginOffsetFromSyncBase;
- bNeedToSet_DurationIncludesDelayBeyondSyncbase = TRUE;
- }
- }
- ULONG32 ulActualDurBeyondSyncBase =
- ulDuration + ulDelayBeyondSyncBase - ulChildDelayBeyondStartOfThis;
- #endif
- BOOL isEndsyncIDrestarting = (SMILEventSourceID ==
- pSyncNode->m_pElement->m_nEndsyncEventSourceTag &&
- pTmpVal->m_pElement->m_pNode->m_id ==
- pSyncNode->m_pElement->m_EndsyncEventSourceID &&
- // /Not really restarting if starting *early*:
- SMILTimelineStatusStartScheduledForLater !=
- curSMILTimelineStatus);
- BOOL isEndsyncFirst = SMILEventSourceFirst ==
- pSyncNode->m_pElement->m_nEndsyncEventSourceTag;
- BOOL isEndsyncFirstRestarting = isEndsyncFirst &&
- bPrepForRestartNeeded &&
- // /Make sure this is the first one restarting:
- (ulMaxEndTime-
- CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR <
- lEffectiveResolvedTime);
- ULONG32 ulParentHardStop = ulMaxEndTime;
- // /If ID or first is restarting at end, we should just
- // end without using a fudge factor):
- if (!isEndsyncIDrestarting && !isEndsyncFirstRestarting)
- {
- ulParentHardStop +=
- CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR;
- }
- else
- {
- // /Must be restarting if parent dur is based on us:
- HX_ASSERT(bPrepForRestartNeeded &&
- SMILTimelineStatusNeverScheduled !=
- pSyncNode->m_pElement->m_nEndsyncEventSourceTag);
- }
- // /If endsync is first and restarting of this element
- // means its prior play ended and thus a *first*
- // child of parent has ended, parent should end *now*:
- if ( (ulParentHardStop <= lEffectiveResolvedTime ||
- // /If ID or 1st is restarting, parent is done:
- isEndsyncIDrestarting || isEndsyncFirstRestarting) &&
- (isEndsyncFirst ||
- // /Fixes PR 59584(endsyncIDwithRestart ver)
- // where ID'd element restarts, thus ending
- // itself and its parent in the process:
- isEndsyncIDrestarting ||
- // /For final PR 62688 fix: don't start if
- // endsync="all" parent has played all kids:
- bEndsyncIsAllAndAllAreDone) )
- {
- goto doneWithRestartCode;
- }
- }
- else if (SMILExcl == pSyncNode->m_tag &&
- pSyncNode->m_pElement->m_pTimelineElement &&
- !pSyncNode->m_pElement->m_bHasExplicitDur &&
- !pSyncNode->m_pElement->m_bHasExplicitEnd &&
- pSyncNode->m_pElement->m_pTimelineElement->
- numChildDursAdded() == 0 &&
- // /Resolved *at* time must be <= excl's delay
- // otherwise excl has come and gone:
- (ULONG32)pTmpVal->getWhenTimeWasResolved() >
- ulSyncBaseDelay &&
- // /Fixes case where scheduled begin time >0 wasn't
- // used until just-in-time & we do want to use it:
- pTmpVal->getTimeType() == SmilTimeEvent &&
- // /In case 1st child begin="5s" and other child
- // event-begins prior to that, we want it to begin:
- !pSyncNode->m_pElement->m_pTimelineElement->
- hasChildWithScheduledBegin() &&
- // /However, if it has endsync="all", then it has
- // unresolved (open) duration, not 0; fixes PR 53527:
- pSyncNode->m_pElement->m_nEndsyncEventSourceTag !=
- SMILEventSourceAll)
- {
- // /Fixes version of PR 56690 where excl has no explicit
- // end or dur and has no children with already-scheduled
- // begin time(s); sucn an excl has a 0 duration:
- goto doneWithRestartCode;
- }
- if ((UINT32)-1 != ulMaxEndTime)
- {
- UINT32 ulNewEndTime =(UINT32)lEffectiveResolvedTime +
- ulNewDuration;
- if ((UINT32)-1 != ulNewDuration)
- {
- if (ulNewEndTime > ulMaxEndTime)
- {
- // /Reduce it so it ends when parent does:
- // /XXXEH- need to reverse these --v
- ulNewDuration -= (ulNewEndTime-ulMaxEndTime);
- }
- }
- else
- {
- // /Fixed this logic once and for all so PR 56690
- // stays fixed & repro for PR 50572 doesn't break
- // on first click:
- // /(Using a temp var instead of actually changing
- // ulNewDuration here fixes PR 62408 and doesn't
- // break PR 56690 nor PR 50572 (and even fixes post-
- // 1st restart bug in PR 50572 repro):
- ULONG32 ulTmpNewDuration = ( (LONG32)ulMaxEndTime >
- lEffectiveResolvedTime) ?
- ulMaxEndTime -
- (ULONG32)lEffectiveResolvedTime : 0;
- // /This is needed for PR 63650 fix:
- ulMaxDuration = ulTmpNewDuration;
- if (0 == ulTmpNewDuration)
- {
- // /Fixes version of PR 56690 where parent
- // has an explicit end or dur and
- // pTmpVal->m_pElement is a time container
- // (if it were media, instertTimelineElem...()
- // would handle the out-of-bounds begin):
- goto doneWithRestartCode;
- }
- }
- }
- }
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG)
- {FILE* f1 = ::fopen("c:\smil2.txt", "a+"); ::fprintf(f1, "npTmpVal->m_idRef= %s, ulNewDuration=%lu, lEffectiveResolvedTime=%ld ulMaxEndTime=%lu, bPrepForRestartNeeded=%lu n", (const char*)pTmpVal->m_idRef, ulNewDuration, lEffectiveResolvedTime, ulMaxEndTime, (UINT32)bPrepForRestartNeeded); ::fclose(f1);}
- #endif
- // /Now, add the track in:
- HX_ASSERT(pTmpVal->m_pElement->m_pTimelineElement);
- pTmpVal->m_pElement->m_pTimelineElement->
- setDelayEventResolved(TRUE);
- if (bPrepForRestartNeeded)
- {
- // /FALSE means restart is not due to parent restart:
- pTmpVal->m_pElement->prepForRestart(FALSE,
- lEffectiveResolvedTime);
- }
- if (ulMaxDuration == (UINT32)-1)
- {
- // /Makes sure <excl end="30s"><ref end="40s"/></excl>
- // only plays for 30s (along with fix for PR 63650):
- ulMaxDuration = ulNewDuration;
- }
- // /If we're restarting, we need to reset the duration
- if (bPrepForRestartNeeded)
- {
- // /XXXEH- need to account for min/max constraints here:
- // /If we're restarting and we're not being constrained
- // by our time container and we don't have an explicitly-
- // set duration, then we need to reset these and play
- // indefinitely:
- if ((UINT32)-1 == ulNewDuration)
- {
- #if defined(XXXEH_20010620_OLD_SMIL2_DRAFT_SEMANTICS_FOR_RESTART_DUR_CALCULATION)
- HX_ASSERT(0 && "ehodge note to self: check spec on restart dur.");
- pTmpVal->m_pElement->m_ulOriginalDuration =
- pTmpVal->m_pElement->m_ulMaxDuration = (UINT32)-1;
- /* XXXEH- need to reset this to FALSE via new method:
- pTmpVal->m_pElement->m_pTimelineElement->
- m_bMaxDurationSet = FALSE;
- */
- // /This should be *unresolved*, not *intrinsic dur
- // of media*, if this has no resolved end time after
- // lEffectiveResolvedTime and is being restarted but
- // *does* have an event-based end time. (See
- // "// if all ends are before the begin, bad interval"
- // in SMIL 2.0 Timing Spec):
- // /We need to do this otherwise it will only play
- // for the media's intrinsic duration:
- ulNewDuration = WAY_IN_THE_FUTURE;
- #endif
- }
- // /XXXEH- need to account for min/max constraints here:
- pTmpVal->m_pElement->m_pTimelineElement->resetDuration(
- ulNewDuration);
- // /Fixes restarting an element whose parent has a set
- // dur; prior to this, it would override the parent dur:
- pTmpVal->m_pElement->m_pTimelineElement->setMaxDuration(
- ulMaxDuration);
- }
- // /we just want to set the max duration to avoid affecting
- // our parent's end time:
- else
- {
- pTmpVal->m_pElement->m_pTimelineElement->setMaxDuration(
- // /Using this instead of ulNewDuration fixes
- // PR 63650 (which broke when fix for PR 62408,
- // above, was put in):
- ulMaxDuration);
- }
- // /While fixing PR 55253, a par that restarts was imposing
- // old duration on its children when setDelay() was called
- // before resetDuration(), above, so that's why setDelay()
- // is now being called later, here:
- pTmpVal->m_pElement->m_pTimelineElement->setDelay(
- lEffectiveResolvedTime, FALSE);
- bREFSomeScheduleWasChanged = TRUE;
- // /iF there are two children that start at time 0, and the
- // first should play but pause immediately while the second
- // plays, then we must add the first before playback and then
- // let the second interrupt the first during blackback:
- if (bDoHandleExclBeforePlaybackStarts && bIsInExcl)
- {
- HX_ASSERT(!((*pExclChildAddedBeforePlayback)[(const char*)
- pExclAncestor->m_id]));
- if (pExclChildAddedBeforePlayback && pExclAncestor)
- {
- (*pExclChildAddedBeforePlayback)[(const char*)
- pExclAncestor->m_id] = (void*)TRUE;
- }
- }
- } // /End if(bAddTrack).
- doneWithRestartCode:
- // /We need to be sure to remove a time that is in the past (or
- // is otherwise used herein) from the pendingList; this also
- // advances the lPos to the next one:
- // /But wait, there's more!: We don't want to remove a time if
- // we just updated its time to later due to a priorityClass
- // deferral (via peers or higher="defer"):
- if (!bTimeValWasDeferred)
- {
- HX_ASSERT(m_pPendingBeginTimeList->GetCount());
- // /Checking the count before deleting fixes a random crash
- // in "BUG-20010611_firstExclChild...". I can't figure out
- // where else it might have been deleted during lPos's life:
- if (m_pPendingBeginTimeList->GetCount())
- {
- m_pPendingBeginTimeList->RemoveAt(lPosOfCurTmpVal);
- }
- // /Post-PR 85885-fix cleanup fix: need to remove undeferEvent
- // from pTmpVal->m_pElement's m_pBeginTimeList if resume just
- // happened, otherwise a subsequent play-to-end of the media
- // that pTmpVal's element originally deferred past would result
- // in that element erroneously playing again:
- if (pTmpVal->isUndeferEvent())
- {
- HX_ASSERT(pTmpVal->m_pElement->m_pBeginTimeList);
- if (pTmpVal->m_pElement->m_pBeginTimeList)
- {
- CHXSimpleList* pBeginList =
- pTmpVal->m_pElement->m_pBeginTimeList;
- // /First, remove any resume events in the list:
- lPos = pBeginList->GetHeadPosition();
- while (lPos)
- {
- LISTPOSITION lPosOfCurTmpVal = lPos;
- // /Gets val @ lPos then moves it to next node:
- SmilTimeValue* pCurListValue =
- (SmilTimeValue*)pBeginList->GetNext(lPos);
- if (!pCurListValue || !pCurListValue->m_pElement)
- {
- HX_ASSERT(pCurListValue &&
- pCurListValue->m_pElement);
- continue;
- }
- if (pCurListValue->isUndeferEvent())
- {
- HX_ASSERT(pTmpVal == pCurListValue);
- // /Get rid of it from the list:
- pBeginList->RemoveAt(lPosOfCurTmpVal);
- break; // /Done; only 1 defer can be in list.
- }
- }
- }
- }
- }
- }
- else // / i.e., !(lEffectiveResolvedTime <= lCurTime)
- {
- // /Since the list is sorted by time, we know we're done handling
- // times that are resolved to lCurTime or earlier:
- // /XXXEH- revisit this (and make sure the @%$#@! list is
- // temporally sorted; as of 20010307, if you have
- // <ref1 begin="ref2.beginEvent"/> and <ref2 begin="0s;7s"/>,
- // the following break will happen before the event-arc time
- // gets seen because ref2's begin of 7s is ahead in the list:
- #if defined(XXXEH_NEED_TEMPORAL_SORTING_FOR_THIS_OPTIMIZATION)
- break;
- #endif /* XXXEH_NEED_TEMPORAL_SORTING_FOR_THIS_OPTIMIZATION. */
- }
- } // /End while (lPos...) [end handling pending begin times].
- // /Go through m_pPendingEndTimeList now:
- lPos = NULL;
- if (m_pPendingEndTimeList)
- {
- lPos = m_pPendingEndTimeList->GetHeadPosition();
- }
- if (bDoHandleExclBeforePlaybackStarts)
- {
- goto cleanup;
- }
- 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_pPendingEndTimeList->GetNext(lPos);
- if (!pTmpVal || !pTmpVal->m_pElement)
- {
- // /List shouldn't have an empty node or a node w/NULL element:
- HX_ASSERT(pTmpVal && pTmpVal->m_pElement);
- // /Get rid of it from the list:
- m_pPendingEndTimeList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- LONG32 lEffectiveResolvedTime = 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_pPendingEndTimeList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- if (pTimeValEndToggleToBeIgnored &&
- pTmpVal->isSameTimeValue(pTimeValEndToggleToBeIgnored))
- {
- // /Ignore it since it was used, above, to begin the element and
- // shouldn't also be used to end it:
- m_pPendingEndTimeList->RemoveAt(lPosOfCurTmpVal);
- 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;
- BOOL bCurElementIsTimeContainer =
- isTimeContainerObject(pTmpVal->m_pElement->m_pNode);
- // /NOTE:we need to recalculate all these here, even though they were
- // calculated above for begin-time-list handling, because that begin-
- // time-handling code may have altered some of the values used here:
- SMILTimelineStatus curSMILTimelineStatus = SMILTimelineStatusUnknown;
- 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
- {
- if (lElementCurEndTime==(-1) ||
- lElementCurEndTime > lCurTime)
- {
- curSMILTimelineStatus =
- SMILTimelineStatusCurrentlyPlaying;
- }
- else
- {
- curSMILTimelineStatus =
- SMILTimelineStatusFinishedPlaying;
- }
- }
- }
- // /We should be in one of these four states; anything else means
- // there's an inconsistency somewhere:
- HX_ASSERT (SMILTimelineStatusUnknown != curSMILTimelineStatus);
- INT32 lResolvedToTimeWithoutOffset =
- pTmpVal->getResolvedToTimeWithoutOffset();
- INT32 lEventTimeOffset = pTmpVal->getTimeOffset();
- INT32 lTimeWithFullOffset =
- lResolvedToTimeWithoutOffset + lEventTimeOffset;
- // /Now, see if this pending end time is ready to be used:
- if (lEffectiveResolvedTime <= lCurTime)
- {
- // /Unless this element is currently playing, we don't need to
- // do anything until a valid begin time gets resolved:
- if (SMILTimelineStatusCurrentlyPlaying == curSMILTimelineStatus)
- {
- if (!pTmpVal->m_pElement->m_pTimelineElement)
- {
- retval = HXR_UNEXPECTED;
- HX_ASSERT(pTmpVal->m_pElement->m_pTimelineElement);
- goto cleanup;
- }
- else
- {
- // /Just call RemoveTrack() at the time we want it gone,
- // and this function we're in has waited for any positive
- // offset to an event before trying to remove the track,
- // so we've managed the scheduling part so, unlike with
- // AddTrack(), the core hasn't had to:
- if (NULL != pTmpVal->m_pElement->m_pHandler ||
- bCurElementIsTimeContainer)
- {
- // /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;
- // /Fixes PR 50676 part 5: we need to notify our
- // parent that the duration has changed since our
- // end may determine our parent's end (e.g.,
- // parent endsync="[our ID]" or endsync="first"):
- pTmpVal->m_pElement->m_pTimelineElement->resetDuration(
- pTmpVal->m_pElement->m_ulDuration);
- m_pTimelineElementManager->notify((const char*) pTmpVal->m_pElement->m_pNode->m_id);
- }
- bREFSomeScheduleWasChanged = 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;
- goto cleanup;
- }
- }
- }
- // /We need to be sure to remove a time that we use from the
- // pendingList; this also advances the lPos to the next one:
- m_pPendingEndTimeList->RemoveAt(lPosOfCurTmpVal);
- }
- else // /effective resolved time is in the future:
- {
- // /Note: if no earlier begin time has yet been resolved then
- // there's no reason to set the end time, even if it is
- // resolved:
- if (SMILTimelineStatusStartScheduledForLater ==
- curSMILTimelineStatus &&
- lElementCurEndTime > lEffectiveResolvedTime )
- {
- // /If element is scheduled to play later and this new
- // end time is prior to that, then we should just ignore
- // this end time for now. Note: if this end time is in
- // the future but still earlier than any resolved begin,
- // we still may need this end time if another begin
- // gets resolved to a time that is prior to this end time:
- if (lEffectiveResolvedTime > // /XXXEH- TODO: ">=" instead?!?
- lElementCurBeginTime)
- {
- // /OK, so this new end time is later than the currently-
- // scheduled begin time and is earlier than the currently-
- // scheduled end time (if any), so let's use it as the
- // end time of the next "interval":
- retval = pTmpVal->m_pElement->setEndTime(this);
- bREFSomeScheduleWasChanged = TRUE;
- // /XXXEH- do we want to call resetDuration()?!?
- // ASSERT for debugging purposes:
- HX_ASSERT(0);
- // /XXXEH- use m_ulDelay+m_ulDuration in
- // comparisons below if m_bEndOffsetSet is false?!?:
- // otherwise, use that sum PLUS m_lEndOffset?????
- // /Recalculate cur end time now that it's been
- // set, above:
- lElementCurEndTime =
- // /XXXEH-??:
- // (pTmpVal->m_pElement->m_bEndOffsetSet?
- // pTmpVal->m_pElement->m_lEndOffset:0) +
- pTmpVal->m_pElement->m_ulDelay +
- pTmpVal->m_pElement->m_ulDuration;
- // /XXXEH- TODO: is this all and/or what we want to do?:
- pTmpVal->m_pElement->m_pTimelineElement->resetDuration(
- lElementCurEndTime -
- lElementCurBeginTime);
- }
- }
- // /Since the list is sorted by time, we know we're done handling
- // times that are resolved to lCurTime or earlier:
- break;
- } // /End "else // /effective resolved time is in the future".
- } // /End handling pending end times.
- #if 0 // /XXXEH- TODO: enable this code and test it!!
- if (bREFSomeScheduleWasChanged)
- {
- // /XXXEH- TODO: prevent circular references from causing
- // this to spin out of control, e.g.,
- // <ref id="ref1" begin="0s; ref2.begin" />
- // <ref id="ref2" begin="ref1.begin" />
- // /Now, call this function in case some dependent
- // element's timing became resolved to now due to the update
- // to pTmpVal->m_pElement's timing, above:
- BOOL bSomeDependentElementScheduleChanged = FALSE;
- HX_RESULT pnr = HXR_OK;
- do
- {
- pnr = checkPendingBeginAndEndTimes(lCurTime, iCurrentGroupIndex,
- bSomeDependentElementScheduleChanged,
- ++lRecursionCount,
- pPauseDisplayHideElementList,
- pPauseDisplayDisableElementList, FALSE);
- }while (lRecursionCount<MAX_PENDING_CHECK_CALLDEPTH &&
- HXR_OK==pnr && bSomeDependentElementScheduleChanged);
- }
- #endif
- cleanup:
- HX_DELETE(pExclChildAddedBeforePlayback);
- return retval;
- }
- /* This looks to see if any stream events in the list have a begin time
- * that is now at or earlier than lCurTime. If any such are found, then
- * the associated URL is hurled.
- */
- CHXMapStringToOb*
- CSmilParser::findNextPendingOnLoadURL(UINT32 ulCurTime)
- {
- // /Look through the list of "onLoad" URLs and fire off any whose time
- // has been exceeded:
- // /Handle begin times that are ready to go:
- LISTPOSITION lPos = NULL;
- if (m_pOnLoadURLList)
- {
- lPos = m_pOnLoadURLList->GetHeadPosition();
- }
- // /Helps Fix PR 67170: this now handles removing all but the last of
- // simultaneous hurls to the same rn:sendTo+target, so a long seek back
- // or a long seek forward will skip all but the last of each rn-sendTo
- // link whose time is less than the seeked-to time. Otherwise we'd be
- // simultaneously hurling possibly many links that would be immediately
- // replaced. The end result is a better user experience, but will not
- // necessarily leave the sendTo app in the state it would have been had
- // normal (seek-less) playback arrived at that time in the presentation
- // (especially if a "back" button exists in the app).
- // /Keep a map of rn:sendTo+target names, each entry containing the most
- // temporally-recent-but-not-exceeding-ulCurTime one, and a matching map
- // for their start times, calculated below:
- CHXMapStringToOb* pSendToTargetMapOfAnchorsToBeHurledNow = NULL;
- CHXMapStringToOb* pMapStartTimeToSendToPlusTarget = NULL;
- // /Go through and see if anybody has a begin time that's ready to become
- // their active begin time:
- while (lPos)
- {
- LISTPOSITION lPosOfCurAnchor = lPos;
- // /Gets val at lPos and then moves lPos to next node in list:
- CSmilAAnchorElement* pCurAnchor =
- (CSmilAAnchorElement*)m_pOnLoadURLList->GetNext(lPos);
- if (!pCurAnchor)
- {
- // /List shouldn't have an empty node:
- HX_ASSERT(pCurAnchor);
- // /Get rid of it from the list:
- m_pOnLoadURLList->RemoveAt(lPosOfCurAnchor);
- continue;
- }
- BOOL bLaunchHyperlink = FALSE;
- // /First, we need to get ulCurTime into local, sync-base time
- // coordinates because isLinkActiveAtTime() expects a time relative
- // to the anchor's sync-base, not to the start of the group:
- ULONG32 ulCurSyncBaseTime = ulCurTime;
- SMILNode* pSyncAncestor = getSyncAncestor(
- pCurAnchor->m_pNode);
- if (pSyncAncestor && pSyncAncestor->m_pElement &&
- (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
- {
- if (ulCurTime < pSyncAncestor->m_pElement->m_ulDelay)
- {
- continue; // /Parent not even active yet.
- }
- else
- {
- ulCurSyncBaseTime =
- ulCurTime - pSyncAncestor->m_pElement->m_ulDelay;
- }
- }
- else
- {
- continue; // /Has no sync-base or has an unresolved one.
- }
- ULONG32 ulAnchorBeginOffset = 0;
- ULONG32 ulAnchorStartTime = 0;
- ULONG32 ulBeginRelativeToSyncBase = (UINT32)-1;
- // /If delay isn't set, then fall through to else, below, which
- // calculates the anchor's delay based on its sync-base time (which
- // is its sync-parent's begin time unless its sync-parent is a seq,
- // in which case the sync-base time is the end of the prev timeline
- // element child in the seq):
- if ((UINT32)-1 != pCurAnchor->m_ulDelay &&
- pCurAnchor->m_bTimeValueSet)
- {
- // /Moving this out of the above if() and inside this block fixes
- // PR 99597; before, if isLinkActiveAtTime() returned FALSE, even
- // though there was explicit timing on the linke, the else, below,
- // would get executed, often setting bLaunchHyperlink to TRUE when
- // it should have just been left FALSE:
- if (pCurAnchor->isLinkActiveAtTime(ulCurSyncBaseTime,
- ulBeginRelativeToSyncBase))
- {
- ulAnchorStartTime = ulBeginRelativeToSyncBase +
- // /Get it into group time, not local time:
- (ulCurTime - ulCurSyncBaseTime);
- bLaunchHyperlink = TRUE;
- }
- // /else link no longer or not yet active, so ignore it.
- }
- // /no explicit timing was set on the anchor, so see if it's
- // got a delay set &/or a begin offset set; if not, use its sync-
- // parent's begin (or use end of its prev seq sibling if in a seq):
- else
- {
- ulAnchorStartTime = pCurAnchor->m_ulDelay;
- if ((UINT32)-1 == ulAnchorStartTime)
- {
- if (pCurAnchor->m_bAnchorBeginOffsetSet)
- {
- ulAnchorBeginOffset = pCurAnchor->m_lAnchorBeginOffset;
- }
- else if (pCurAnchor->m_bBeginOffsetSet)
- {
- ulAnchorBeginOffset = (UINT32)pCurAnchor->m_lBeginOffset;
- if (pCurAnchor->m_lBeginOffset < 0)
- {
- ulAnchorBeginOffset = 0;
- }
- }
- // /Be sure to add on parent's delay, if any:
- if (pCurAnchor->m_pNode &&
- pCurAnchor->m_pNode->m_pParent &&
- pCurAnchor->m_pNode->m_pParent->m_pElement)
- {
- SMILNode* pSyncAncestor =
- getSyncAncestor(pCurAnchor->m_pNode);
- if (pSyncAncestor &&
- SMILSeq == pSyncAncestor->m_tag)
- {
- CSmilElement* pSyncBaseElement =
- pSyncAncestor->m_pElement;
- // /Fixes PR 53363: syncBase of seq child is
- // end of prior sibling, not parent's begin:
- SMILNode* pPriorSibling =
- getPrevNode(pCurAnchor->m_pNode);
- if (!pPriorSibling)
- {
- // /No prev sibling so sync base is seq parent:
- pSyncBaseElement = pSyncAncestor->m_pElement;
- }
- else if (pPriorSibling->m_pElement && (UINT32)-1 !=
- pPriorSibling->m_pElement->m_ulDelay &&
- (UINT32)-1 !=
- pPriorSibling->m_pElement->m_ulDuration)
- {
- pSyncBaseElement = pPriorSibling->m_pElement;
- }
- // /Prior sibling should not be a timeline object
- // otherwise its end should be known:
- else if (!isTimelineObject(pPriorSibling))
- {
- SMILNode* pPriorSiblingFirstChild =
- pPriorSibling->getFirstChild();
- if (!pPriorSiblingFirstChild)
- {
- // /XXXEH- TODO: get prior-prior sibling and
- // try again:
- continue;
- }
- pSyncBaseElement =
- pPriorSiblingFirstChild->m_pElement;
- BOOL bPriorSibIsTimelineObject =
- isTimelineObject(pPriorSiblingFirstChild);
- HX_ASSERT(bPriorSibIsTimelineObject);
- }
- // /Skip this link because prior timeline object does
- // not yet have a resolved end time (which it should):
- else
- {
- HX_ASSERT(0);
- continue;
- }
- if (pSyncBaseElement)
- {
- HX_RESULT pnrStart = HXR_OK;
- // /Fixes PR 58429: if syncBaseElement is actually
- // the parent seq, then use its begin time, not
- // its end time, as the sync base:
- if (pSyncBaseElement == pSyncAncestor->m_pElement)
- {
- pnrStart = pSyncBaseElement->
- getCurrentScheduledStartTime(
- ulAnchorStartTime);
- }
- else // /Use end of prior seq sibling as sync base:
- {
- pnrStart = pSyncBaseElement->
- getCurrentScheduledStopTime(
- ulAnchorStartTime);
- }
- // /Now, add begin offset, if any, to
- // sync base's end time (but not if end time
- // is not valid or is indefinite):
- if (HXR_OK == pnrStart &&
- ulAnchorStartTime < WAY_IN_THE_FUTURE)
- {
- ulAnchorStartTime += ulAnchorBeginOffset
- // /Add fudge factor in case
- // syncBaseElement ends when parent
- // does, in which case we don't want
- // to hurl because we're past the end:
- +100;
- }
- }
- }
- else if (pSyncAncestor && pSyncAncestor->m_pElement)
- {
- #if XXXEH_HOLD_UNTIL_I_FIX_BUG_WHEN_PAR_OR_EXCL_PARENT_HAS_DELAY
- ulAnchorStartTime = (UINT32)-1; // /Start unresolved...
- if ((UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
- {
- ulAnchorStartTime =
- pSyncAncestor->m_pElement->m_ulDelay;
- }
- if (pSyncAncestor->m_pElement->m_bBeginOffsetSet &&
- WAY_IN_THE_FUTURE !=
- pSyncAncestor->m_pElement->m_ulDelay)
- {
- ulAnchorStartTime += (UINT32)
- (pSyncAncestor->m_pElement->m_lBeginOffset);
- }
- #else
- HX_RESULT pnrStart = pSyncAncestor->m_pElement->
- getCurrentScheduledStartTime(ulAnchorStartTime);
- // /Now, add begin offset, if any, to
- // sync base's end time:
- ulAnchorStartTime += ulAnchorBeginOffset;
- #endif
- #if defined(_DEBUG)
- ULONG32 ulStartTime2 = (UINT32)
- (pSyncAncestor->m_pElement->m_lBeginOffset >= 0?
- pSyncAncestor->m_pElement->m_lBeginOffset : 0);
- ulStartTime2 += ulAnchorBeginOffset;
- HX_ASSERT(ulAnchorStartTime == ulStartTime2);
- #endif
- }
- else
- {
- ulAnchorStartTime = (UINT32)-1; // /Unresolved time.
- }
- }
- }
- if (ulAnchorStartTime <= ulCurTime)
- {
- // /XXXEH: check if ulAnchorEndTime >= ulCurTime as well (see:
- // "BUG-20011113_letOnLoadURLhurlAt10sThenStopItAndResumeMainThenSeek..."):
- bLaunchHyperlink = TRUE;
- }
- }
- if (!bLaunchHyperlink)
- {
- /* // /XXXEH- TODO: pre-sort this temporally:
- // But, NOTE: we *can't* sort these due to not-yet-knowable
- parental timing, e.g., excl pause & defer, and par begin=[event]:
- // /This one's begin time has not yet been reached, and this
- // list is temporally sorted so we're done for now:
- break;
- */
- continue; // /do this until list is temporally sorted.
- }
- else
- {
- // /Remove: it'll be hurled now or be determined to be ignored:
- m_pOnLoadURLList->RemoveAt(lPosOfCurAnchor);
- // /Helps fix PR 67170: don't return until we've found the last
- // of the ones ready to go for the associated "sendTo" app,
- // ignoring the others since they'll be replaced immediately
- // anyway:
- if (!pSendToTargetMapOfAnchorsToBeHurledNow)
- {
- pSendToTargetMapOfAnchorsToBeHurledNow = new CHXMapStringToOb;
- if (!pSendToTargetMapOfAnchorsToBeHurledNow)
- {
- goto cleanup; // /Do nothing if system is out of memory.
- }
- }
- // /If no sendTo specified, then defaults to "_rpbrowser" if
- // external=TRUE, otherwise defaults to "_rpengine":
- CHXString keyStr;
- if (pCurAnchor->m_sendTo.IsEmpty() ||
- // /If external is FALSE, sendTo is ignored:
- !pCurAnchor->m_bExternal)
- {
- if (pCurAnchor->m_bExternal)
- {
- keyStr = "_rpbrowser";
- }
- else
- {
- keyStr = "_rpengine";
- }
- }
- else // /use sendTo value as the key:
- {
- keyStr = (const char*)pCurAnchor->m_sendTo;
- }
- // /If link "target" is specified, append it to the key since a
- // target is a specific instance of the sendTo app:
- if (!pCurAnchor->m_target.IsEmpty())
- {
- keyStr += pCurAnchor->m_target;
- }
- HX_ASSERT(!keyStr.IsEmpty());
- if (!keyStr.IsEmpty())
- {
- // /If we didn't just seek, then just return the first one found
- // that's time-valid and let the next, if any, be hurled at the
- // next onTimeSync:
- if (!m_bHandlePostSeekOnLoadURLs)
- {
- (*pSendToTargetMapOfAnchorsToBeHurledNow)[keyStr] =
- (void*)pCurAnchor;
- goto cleanup;
- }
- if (!pMapStartTimeToSendToPlusTarget)
- {
- pMapStartTimeToSendToPlusTarget = new CHXMapStringToOb;
- if (!pMapStartTimeToSendToPlusTarget)
- {
- goto cleanup; // /Do nothing if system is out of memory.
- }
- }
- // /Now, see if map[key] time is earlier than current; if so,
- // replace it with current anchor start time:
- UINT32 ulCurrentlyMappedAnchorStartTime = (UINT32)-1;
- BOOL bCurrentlyMappedAnchorStartTimeIsValid = FALSE;
- if (pMapStartTimeToSendToPlusTarget->Lookup(
- (const char*)keyStr, (void*&)ulCurrentlyMappedAnchorStartTime))
- {
- bCurrentlyMappedAnchorStartTimeIsValid = TRUE;
- }
- // /If map entry didn't already exist or it did but new time
- // is same or more recent, then replace it with the new value:
- if (!bCurrentlyMappedAnchorStartTimeIsValid ||
- // /Note: do ">=", not just ">", to make sure lexically-
- // last of a same-timed pair wins:
- ulAnchorStartTime >= ulCurrentlyMappedAnchorStartTime)
- {
- (*pSendToTargetMapOfAnchorsToBeHurledNow)[(const char*)
- keyStr] = (void*)pCurAnchor;
- (*pMapStartTimeToSendToPlusTarget)[(const char*)keyStr] =
- (void*)ulAnchorStartTime;
- }
- }
- else
- {
- goto cleanup; // /can't recover from error.
- }
- }
- }
- cleanup:
- m_bHandlePostSeekOnLoadURLs = FALSE;
- HX_DELETE(pMapStartTimeToSendToPlusTarget);
- // /NOTE: May be NULL; if not, caller must delete when done:
- return (pSendToTargetMapOfAnchorsToBeHurledNow);
- }
- // /Returns TRUE if any other element is awaiting an activateEvent (click or
- // other form of user activation) to begin or end (fixes PR 56503):
- BOOL
- CSmilParser::hasActivateEventListener(const char* pMediaID,
- INT16 iCurrentGroupIndex)
- {
- BOOL bSomeoneIsListeningForActivateEvent = FALSE;
- // /Look for begin times that are awaiting pMediaID user activation:
- LISTPOSITION lPos = NULL;
- CHXSimpleList* pCurList = m_pBeginEventList;
- for (INT16 iList=0; iList<2 && !bSomeoneIsListeningForActivateEvent; iList++)
- {
- if (1==iList)
- {
- pCurList = m_pEndEventList;
- }
- if (pCurList)
- {
- lPos = pCurList->GetHeadPosition();
- }
- else
- {
- continue;
- }
- // /Go through and see if anybody has a begin time that's ready to
- // become their active begin time:
- while (lPos)
- {
- LISTPOSITION lPosOfCurTmpVal = lPos;
- // /Gets val at lPos and then moves lPos to next node in list:
- SmilTimeValue* pTmpVal =
- (SmilTimeValue*)pCurList->GetNext(lPos);
- if (!pTmpVal || !pTmpVal->m_pElement ||
- !pTmpVal->m_pElement->m_pNode)
- {
- // /List shouldn't have empty node or node w/NULL element:
- HX_ASSERT(pTmpVal && pTmpVal->m_pElement &&
- pTmpVal->m_pElement->m_pNode);
- // /Get rid of it from the list:
- pCurList->RemoveAt(lPosOfCurTmpVal);
- continue;
- }
- // Ignore this timeValue if it's element is not in the current
- // group:
- if (pTmpVal->m_pElement->m_pNode->m_nGroup != iCurrentGroupIndex)
- {
- continue;
- }
- const char* pEventName = pTmpVal->getEventName();
- const char* pIDRef = pTmpVal->getIdRef();
- if (pEventName && pIDRef &&
- 0==strcmp("activateEvent", pEventName) &&
- 0==strcmp(pMediaID, pIDRef))
- {
- // /XXXEH- optimize for the following cases; if any evaluate
- // to TRUE, then don't return TRUE from here:
- // (1) If pTmpVal->m_pElement's restart="never" & m_pElement
- // has played already.
- // (2) If pTmpVal->m_pElement's restart="whenNotActive" and
- // m_pElement is currently playing
- // (3) If pTmpVal->m_pElement's parent begin is too late for
- // m_pElement to play based on this activateEvent
- // (4) if pTmpVal->m_pElement's parent end is too early for
- // m_pElement to play based on this activateEvent
- // (5) if pTmpVal is going to *end* on this activateEvent and
- // its parent's end time is earlier than the computed end
- // based on this activateEvent::
- bSomeoneIsListeningForActivateEvent = TRUE;
- break; // /We only need to know if *any* is listening.
- }
- } // end while().
- } // end for().
- return bSomeoneIsListeningForActivateEvent;
- }
- // /This function checks to see if there is already a time value with the
- // exact same characteristics as the one being passed in:
- BOOL
- CSmilParser::isDuplicateEntry(CHXSimpleList* pList,
- SmilTimeValue* pTimeValue)
- {
- BOOL bHasEvilTwin = FALSE;
- if (pList && pTimeValue)
- {
- LISTPOSITION lPos = NULL;
- if (pList)
- {
- lPos = pList->GetHeadPosition();
- }
- while (lPos)
- {
- // /Gets val at lPos and then moves lPos to next node in list:
- SmilTimeValue* pTmpValue = (SmilTimeValue*)pList->GetNext(lPos);
- if (!pTmpValue || !pTmpValue->m_pElement)
- {
- // /List shouldn't have an empty node or a node w/NULL element:
- HX_ASSERT(pTmpValue && pTmpValue->m_pElement);
- continue;
- }
- if (pTimeValue->isSameTimeValue(pTmpValue))
- {
- bHasEvilTwin = TRUE;
- break;
- }
- }
- }
- return bHasEvilTwin;
- }
- HX_RESULT CSmilParser::computeRemoveTime(const char* pszID,
- REF(UINT32) rulRemoveTime)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pszID)
- {
- // Get this element
- CSmilElement* pElement = findElement(pszID);
- if (pElement)
- {
- // Check our erase value
- if (pElement->m_eErase == EraseWhenDone)
- {
- // Get our fill value
- FillType eOurFill = pElement->m_eActualFill;
- // See if our parent is resolved
- BOOL bKnowParentEnd = FALSE;
- BOOL bHasParentElement = FALSE;
- FillType eParentFill = FillDefault;
- const char* pszParentID = NULL;
- UINT32 ulParentEnd = 0;
- if (pElement->m_pNode)
- {
- SMILNode* pSANode = getSyncAncestor(pElement->m_pNode);
- if (pSANode && pSANode->m_pElement)
- {
- UINT32 ulStop = 0;
- HX_RESULT rv = pSANode->m_pElement->getCurrentScheduledStopTime(ulStop);
- if (SUCCEEDED(rv))
- {
- bKnowParentEnd = TRUE;
- ulParentEnd = ulStop;
- }
- // Get the parent's fill value
- eParentFill = pSANode->m_pElement->m_eActualFill;
- // Save the parent id
- pszParentID = (const char*) pSANode->m_id;
- // Do we have a parent CSmilElement?
- CSmilElement* pTmpEl = findElement(pszParentID);
- if (pTmpEl)
- {
- // Set the flag
- bHasParentElement = TRUE;
- }
- }
- }
- // Get the type of time container we're in
- SMILNodeTag eTimeContTag = getSyncTag(pElement->m_pNode);
- // If we are in a <seq>, then get the delay of the
- // next element in the <seq>.
- BOOL bKnowNextDelay = FALSE;
- BOOL bLastInSeq = FALSE;
- UINT32 ulNextDelay = 0;
- if (eTimeContTag == SMILSeq &&
- pElement->m_pTimelineElement)
- {
- CSmilTimelineElement* pDep = pElement->m_pTimelineElement->getDependent();
- if (pDep)
- {
- CSmilElement* pSrcEl = pDep->getSourceElement();
- if (pSrcEl)
- {
- UINT32 ulStart = 0;
- HX_RESULT rv = pSrcEl->getCurrentScheduledStartTime(ulStart);
- if (SUCCEEDED(rv))
- {
- bKnowNextDelay = TRUE;
- ulNextDelay = ulStart;
- }
- }
- // if (pDep->initialDelaySet())
- // {
- // bKnowNextDelay = TRUE;
- // // XXXMEH - DELAY_DUR_FIX
- // ulNextDelay = pDep->getDelay();
- // }
- }
- else
- {
- // If we have no dependent timeline element,
- // then we are the last element in the <seq>
- bLastInSeq = TRUE;
- }
- }
- else if (eTimeContTag == SMILExcl)
- {
- // Get our currently scheduled stop time
- UINT32 ulOurStopTime = 0;
- HX_RESULT rv = pElement->getCurrentScheduledStopTime(ulOurStopTime);
- if (SUCCEEDED(rv))
- {
- // Now we need to look for all our siblings
- // which have a currently scheduled start time
- // after our stop time.
- //
- // Get our excl parent
- SMILNode* pExclParentNode = getSyncAncestor(pElement->m_pNode);
- if (pExclParentNode)
- {
- BOOL bValidMin = FALSE;
- UINT32 ulMinStart = 0;
- SMILNode* pSibling = getTimelineDescendent(pExclParentNode);
- while (pSibling)
- {
- if (pSibling->m_pElement &&
- pSibling->m_pElement != pElement)
- {
- UINT32 ulSibStart = 0;
- rv = pSibling->m_pElement->getCurrentScheduledStartTime(ulSibStart);
- if (SUCCEEDED(rv))
- {
- if (ulSibStart > ulOurStopTime)
- {
- if (bValidMin)
- {
- if (ulSibStart < ulMinStart)
- {
- ulMinStart = ulSibStart;
- }
- }
- else
- {
- ulMinStart = ulSibStart;
- bValidMin = TRUE;
- }
- }
- // /Fixes PR 53175 (& PR 54540):
- // if sibling start time is earlier
- // *but* end time is later, then it
- // resumed after we ended and we
- // should be removed if fill="freeze"
- // as if another sibling just started:
- else
- {
- #if XXXEH_2010419_secondPlayOfFirstInExclNotPlaying_LEGAL_BUT_HITS_THIS_AT_3s
- #error: need to find content that trips this assert and is broken:
- HX_ASSERT(ulSibStart != ulOurStopTime &&
- "same begins in excl; pls email ehodge");
- #endif
- UINT32 ulSibEnd = 0;
- HX_RESULT rcSibEnd =
- pSibling->m_pElement->
- getCurrentScheduledStopTime(
- ulSibEnd);
- HX_ASSERT(HXR_OK == rcSibEnd);
- if (HXR_OK == rcSibEnd &&
- ulSibEnd >= ulOurStopTime)
- {
- // /Guaranteed to be lower
- // than ulMinStart so far:
- ulMinStart = ulOurStopTime;
- bValidMin = TRUE;
- // /All we need is one:
- break;
- }
- }
- }
- }
- pSibling = getTimelineDescendent(pExclParentNode, pSibling);
- }
- // Did we get a valid next start?
- // or a valid resume after our end?
- if (bValidMin)
- {
- bKnowNextDelay = TRUE;
- ulNextDelay = ulMinStart;
- }
- }
- }
- }
- // Switch based on our fill value
- // Note that we use "actual" fill here - that is
- // the "resolved" fill value after all fillDefault and
- // auto are taken into consideration.
- switch (eOurFill)
- {
- // If we don't support transitions, but for some
- // reason have a fill="transition", then we treat
- // it as fill="remove"
- #if !defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- case FillTransition:
- #endif /* #if !defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- case FillRemove:
- {
- // SPEC
- // Specifies that the element will not extend past the end
- // of the last instance of the simple duration
- //
- // Our remove time will be the end of our duration
- // // XXXMEH - DELAY_DUR_FIX
- // rulRemoveTime = pElement->m_ulDelay + pElement->m_ulDuration -
- // (pElement->m_bBeginOffsetSet ? pElement->m_lBeginOffset : 0);
- UINT32 ulStop = 0;
- retVal = pElement->getCurrentScheduledStopTime(ulStop);
- if (SUCCEEDED(retVal))
- {
- rulRemoveTime = ulStop;
- // Do we know our parent's end?
- if (bKnowParentEnd)
- {
- // We know our parent's end, so we need to check if
- // our parent cuts us off. Note that we intentionally
- // check for ">" instead of ">=".
- if (rulRemoveTime > ulParentEnd)
- {
- // Do we actually have a parent?
- if (bHasParentElement)
- {
- // Our parent cuts us off, so we are still active
- // when our parent ends. Therefore, if our parent
- // has a fill value of "freeze" or "hold", then
- // we will have to look at remove time of our
- // parent to know when we need to remove.
- retVal = computeRemoveTime(pszParentID,
- rulRemoveTime);
- }
- }
- }
- }
- }
- break;
- case FillFreeze:
- {
- // SPEC
- // Specifies that the element will extend past the end of the
- // last instance of the simple duration by "freezing" the element
- // state at that point. An element with "freeze" behavior is
- // extended according to the parent time container:
- // - In a par, the element is frozen to extend to the end of the simple
- // duration of the par. In this case, fill="freeze" is equivalent to
- // fill="hold".
- // - In a seq, the element is frozen to extend to the begin of the next
- // element in the seq or until the end of the simple duration of the
- // seq.This will fill any gap in the presentation (although it may have
- // no effect if the next element begins immediately). ]
- // - In an excl, the element is frozen to extend to the begin of the next
- // element to be activated in the excl or until the end of the simple
- // duration of the excl. This will fill any gap in the presentation
- // (although it may have no effect if the next element interrupts the
- // current element). Note that if an element is paused, the active
- // duration has not ended, and so the fill attribute does not (yet)
- // apply.
- //
- // What kind of time container are we in?
- if (eTimeContTag == SMILPar)
- {
- // Do we know our parent's end time? If we
- // don't, then we can't set the remove time
- if (bKnowParentEnd)
- {
- // Is our parent frozen or held?
- if (eParentFill == FillFreeze || eParentFill == FillHold)
- {
- // Do we have a parent CSmilElement?
- if (bHasParentElement)
- {
- // We have a parent CSmilElement and
- // our parent is frozen or held, so we need
- // to check the remove time for our parent
- retVal = computeRemoveTime(pszParentID,
- rulRemoveTime);
- }
- else
- {
- // We don't have a parent CSmilElement,
- // so we must simply take our parent's end time
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- else
- {
- // Our parent is not frozen or held, so our
- // remove time is the end of our parent
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- }
- else if (eTimeContTag == SMILSeq)
- {
- // Are we the last element in the <seq>?
- if (!bLastInSeq)
- {
- // We are not the last element in the <seq>,
- // so do we know the delay of the next element
- // in the <seq>?
- if (bKnowNextDelay)
- {
- // If we are in a <seq> and we have fill="freeze",
- // then we should remove at the start of the
- // next element in the <seq>, taking into account
- // any begin offset of that next element.
- rulRemoveTime = ulNextDelay;
- retVal = HXR_OK;
- }
- }
- else
- {
- // We are the last element in the <seq>, so
- // we will freeze until the end of our time
- // container.
- if (bKnowParentEnd)
- {
- // Is our parent frozen or held?
- if (eParentFill == FillFreeze || eParentFill == FillHold)
- {
- // Do we have a parent CSmilElement?
- if (bHasParentElement)
- {
- // We have a parent CSmilElement, and
- // our parent is frozen or held, so we need
- // to check the remove time for our parent
- retVal = computeRemoveTime(pszParentID,
- rulRemoveTime);
- }
- else
- {
- // We don't have a parent CSmilElement,
- // so we simply take our parent's end time
- // as our remove time.
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- else
- {
- // Our parent is not frozen or held, so our
- // remove time is the end of our parent
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- }
- }
- else if (eTimeContTag == SMILExcl)
- {
- // Do we know the delay of the next element
- // in the <excl>?
- if (bKnowNextDelay)
- {
- // If we are in a <seq> and we have fill="freeze",
- // then we should remove at the start of the
- // next element in the <seq>, taking into account
- // any begin offset of that next element.
- rulRemoveTime = ulNextDelay;
- retVal = HXR_OK;
- }
- }
- }
- break;
- case FillHold:
- {
- // SPEC:
- // Setting this to "hold" has the same effect as setting to
- // "freeze", except that the element is always frozen to extend to the end
- // of the simple duration of the parent time container of the element
- // (independent of the type of time container). For profiles that support
- // a layered layout model (e.g., SMIL 2.0 Language Profile), held elements
- // (elements with fill="hold") will refresh their display area when a layer
- // is added on top then later removed.
- //
- // Do we know our parent's end time? If we
- // don't, then we can't set the remove time
- if (bKnowParentEnd)
- {
- // Is our parent frozen or held?
- if (eParentFill == FillFreeze || eParentFill == FillHold)
- {
- // Do we have a parent CSmilElement?
- if (bHasParentElement)
- {
- // We have a parent CSmilElement, and
- // our parent is frozen or held, so we need
- // to check the remove time for our parent
- retVal = computeRemoveTime(pszParentID,
- rulRemoveTime);
- }
- else
- {
- // We don't have a parent CSmilElement,
- // so we just take our parent's end time
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- else
- {
- // Our parent is not frozen or held, so our
- // remove time is the end of our parent
- rulRemoveTime = ulParentEnd;
- retVal = HXR_OK;
- }
- }
- }
- break;
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- case FillTransition:
- {
- // XXXMEH - temporary fix for fill="transition"
- // XXXMEH - TODO
- // The correct implementation for fill="transition" is to
- // look through all currently scheduled transitions and find the
- // next transition which begins after the end of the active
- // duration of this element covering any part of the screen in
- // which this element is playing. This transition could be
- // on a media element which is outside of this element's
- // time container. However, in most cases, the element will
- // be a sibling of this element. Therefore, temporarily, we
- // will simply look at the elements which are children
- // of our time container. If we don't find a transIn for one
- // on one of these elements, then we treat this as fill="remove".
- UINT32 ulTime = 0;
- HX_RESULT rv = getNextTransitionEnd(pElement, ulTime);
- if (SUCCEEDED(rv))
- {
- rulRemoveTime = ulTime;
- retVal = HXR_OK;
- }
- else
- {
- // We didn't find a transition inside our time
- // time container, so treat this as fill="remove".
- UINT32 ulStop = 0;
- retVal = pElement->getCurrentScheduledStopTime(ulStop);
- if (SUCCEEDED(retVal))
- {
- rulRemoveTime = ulStop;
- }
- // // XXXMEH - DELAY_DUR_FIX
- // rulRemoveTime = pElement->m_ulDelay + pElement->m_ulDuration -
- // (pElement->m_bBeginOffsetSet ? pElement->m_lBeginOffset : 0);
- // retVal = HXR_OK;
- }
- }
- break;
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- }
- }
- else
- {
- // XXXMEH - TODO - final fix for erase="never". Spec says:
- // "The effects of erase=never apply after the active duration
- // of the media object and any fill period (defined by SMIL
- // Timing and Synchronization), and only until other media
- // plays to the region targeted by the media object, or until
- // the same media object restarts."
- //
- // We will implement erase="never" by setting the
- // remove time for erase="never" elements as WAY_IN_THE_FUTURE.
- rulRemoveTime = WAY_IN_THE_FUTURE;
- // Clear the return value
- retVal = HXR_OK;
- }
- }
- }
- return retVal;
- }
- void
- CSmilParser::InitPersistent(UINT32 ulPersistentComponentID,
- IHXValues* pProperties)
- {
- m_ulPersistentComponentID = ulPersistentComponentID;
- if (pProperties)
- {
- pProperties->GetPropertyULONG32("Delay", m_ulPersistentComponentDelay);
- pProperties->GetPropertyULONG32("Duration", m_ulPersistentComponentDuration);
- pProperties->GetPropertyULONG32("ElementWithinTag", (UINT32&)m_elementWithinTag);
- }
- }
- HX_RESULT
- CSmilParser::addResumeEvent(SmilTimeValue* pTimeValue,
- REF(BOOL) bOldResumeEventWasRemoved)
- {
- return addResumeOrUndeferEvent(pTimeValue, bOldResumeEventWasRemoved,
- TRUE);
- }
- HX_RESULT
- CSmilParser::addUndeferEvent(SmilTimeValue* pTimeValue,
- REF(BOOL) bOldDeferEventWasRemoved)
- {
- return addResumeOrUndeferEvent(pTimeValue, bOldDeferEventWasRemoved,
- FALSE);
- }
- // /This function inserts the time value into the pending list, but first
- // checks to see if there is already a pending time value for this element;
- // if so, it removes the old one. It returns TRUE in
- // bOldResumeEventWasRemoved if existing one was removed herein:
- HX_RESULT
- CSmilParser::addResumeOrUndeferEvent(SmilTimeValue* pTimeValue,
- REF(BOOL) bOldEventWasRemoved,
- BOOL bIsResumeEvent)
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "add%sEvent(timeVal's = %s)n", bIsResumeEvent?"Resume":"Undefer",
- (const char*)pTimeValue->m_pElement->m_pNode->m_id);
- ::fclose(f1);
- }
- #endif
- HX_RESULT pnr = HXR_OK;
- bOldEventWasRemoved = FALSE;
- if (pTimeValue)
- {
- LISTPOSITION lPos = NULL;
- if (!m_pBeginEventList)
- {
- m_pBeginEventList = new CHXSimpleList;
- }
- if (!m_pBeginEventList)
- {
- pnr = HXR_OUTOFMEMORY;
- }
- else
- {
- lPos = m_pBeginEventList->GetHeadPosition();
- }
- while (lPos)
- {
- LISTPOSITION lPosOfCurTmpVal = lPos;
- // /Gets val at lPos and then moves lPos to next node in list:
- SmilTimeValue* pTmpValue =
- (SmilTimeValue*)m_pBeginEventList->GetNext(lPos);
- if (!pTmpValue || !pTmpValue->m_pElement)
- {
- // /List shouldn't have an empty node or one w/NULL element:
- HX_ASSERT(pTmpValue && pTmpValue->m_pElement);
- continue;
- }
- if (pTimeValue->m_pElement == pTmpValue->m_pElement)
- {
- if ((bIsResumeEvent && pTmpValue->isResumeEvent()) ||
- (!bIsResumeEvent && pTmpValue->isUndeferEvent()) )
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- {
- FILE* f1 = ::fopen("c:\smil2excl.txt", bFirstExclTrackChangeDebugOut?"w":"a+");
- bFirstExclTrackChangeDebugOut = FALSE;
- ::fprintf(f1, "tadd%sEvent(timeVal's = %s): removing %s %sEvent from event listn",
- bIsResumeEvent? "Resume":"Undefer",
- (const char*)pTimeValue->m_pElement->m_pNode->m_id,
- (const char*)pTmpValue->m_pElement->m_pNode->m_id);
- bIsResumeEvent? "resume":"undefer",
- ::fclose(f1);
- }
- #endif
- // /Get rid of it from the pending list:
- m_pBeginEventList->RemoveAt(lPosOfCurTmpVal);
- // Get rid of it from the map
- removeFromBeginOrEndTimeMap(pTmpValue, SmilBeginTimeList);
- bOldEventWasRemoved = TRUE;
- break;
- }
- }
- }
- // /XXXEH- TODO: add this in temporal order; break out the bottom
- // part of CSmilParser::insertElementWithPendingBeginOrEnd() into
- // its own function 'insertPendingInTemporalOrder()' or the like:
- // /OK to insert the new one now:
- pnr = addBeginEventElement(pTimeValue);
- // /Next, we have to add this as a begin time to the element's
- // begin-time list so it can get resolved the normal way when the
- // resume|defer event happens, which is when the interrupting sibling ends:
- if (HXR_OK == pnr && pTimeValue->m_pElement)
- {
- if (!pTimeValue->m_pElement->m_pBeginTimeList)
- {
- pTimeValue->m_pElement->m_pBeginTimeList = new CHXSimpleList;
- }
- if (!pTimeValue->m_pElement->m_pBeginTimeList)
- {
- pnr = HXR_OUTOFMEMORY;
- }
- else
- {
- CHXSimpleList* pBeginList =
- pTimeValue->m_pElement->m_pBeginTimeList;
- // /First, remove any resume events in the list:
- lPos = pBeginList->GetHeadPosition();
- while (lPos)
- {
- LISTPOSITION lPosOfCurTmpVal = lPos;
- // /Gets val at lPos and then moves lPos to next node in list:
- SmilTimeValue* pTmpValue =
- (SmilTimeValue*)pBeginList->GetNext(lPos);
- if (!pTmpValue || !pTmpValue->m_pElement)
- {
- HX_ASSERT(pTmpValue && pTmpValue->m_pElement);
- continue;
- }
- if ((bIsResumeEvent && pTmpValue->isResumeEvent()) ||
- (!bIsResumeEvent && pTmpValue->isUndeferEvent()) )
- {
- // /Get rid of it from the list:
- pBeginList->RemoveAt(lPosOfCurTmpVal);
- bOldEventWasRemoved = TRUE;
- break;
- }
- }
- // /Now it's OK to stick this new one in:
- pBeginList->AddTail(pTimeValue);
- }
- }
- }
- return pnr;
- }
- HX_RESULT
- CSmilParser::parseDuration(const char* pDuration, CSmilElement* pElement,
- SMILSyncAttributeTag nTag)
- {
- HX_RESULT rc = HXR_OK;
- if(!pDuration)
- {
- return HXR_FAIL;
- }
- const char* pCh = pDuration;
- // check for event-source
- // syntax is: id(a)(4s)
- if(strncmp(pCh, "id(", 3) == 0)
- {
- rc = parseSmil1SyncbaseValue(pCh, pElement, nTag);
- if (SMILSyncAttrEnd == nTag)
- {
- // /This is needed to trick the core into letting the
- // media play when we give it a yet-unresolved end:
- pElement->m_ulDuration = WAY_IN_THE_FUTURE;
- }
- }
- else if(strcmp(pCh, "first") == 0)
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceFirst;
- }
- }
- else if(strcmp(pCh, "last") == 0)
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceLast;
- }
- }
- else if(strcmp(pCh, "all") == 0)
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceAll;
- }
- }
- else if(strcmp(pCh, "indefinite") == 0)
- {
- // /Fixes PR-28674: dur="indefinite" should be allowed on time
- // containers, too:
- #if defined(DONT_ALLOW_INDEFINITE_ON_TIME_CONTAINERS)
- // /XXXEH- TODO: find out from Henry Ping why we're limiting this:
- // this is contrary to the SMIL 1 and SMIL 2 specs:
- if (pElement->m_pNode->m_tag == SMILSeq ||
- pElement->m_pNode->m_tag == SMILExcl ||
- pElement->m_pNode->m_tag == SMILPar)
- {
- rc = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorIndefiniteNotSupported, NULL,
- pElement->m_pNode->m_ulTagStartLine);
- }
- else
- #endif
- if (nTag == SMILSyncAttrMax)
- {
- ; // /Nothing to do;"indefinite" is equivalent to ignoring max value
- }
- else if (nTag == SMILSyncAttrEnd ||
- // /end AND dur can each have the value "indefinite":
- nTag == SMILSyncAttrDur)
- {
- // /NOT setting the following to TRUE helps fix
- // SMIL 2.0 Interop Timing #18.8 where setDuration()
- // wasn't being called on indef-dur element in
- // CSmilParser::durationResolved() so parent never
- // got a chance to properly calculate its endsync behavior.
- // (The player won't go from "live" to a duration once
- // a stream that's still playing is declared to be "live"
- // via the setProperty...("indefiniteduration"...) in
- // handleSource() in SMIL doc renderer:
- #if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)
- pElement->m_bIndefiniteDuration = TRUE;
- #endif
- // /XXXEH- this is needed to trick the core into letting the
- // media play when we give it an indefinite end:
- pElement->m_ulDuration = WAY_IN_THE_FUTURE;
- }
- }
- else if (strncmp(pCh, "marker=", 7) == 0 &&
- (nTag == SMILSyncAttrClipBegin ||
- nTag == SMILSyncAttrClipEnd))
- {
- // Advance past the "marker="
- pCh += 7;
- // Parse the marker
- if (nTag == SMILSyncAttrClipBegin)
- {
- rc = parseMarkerClipBeginEnd(pCh,
- pElement->m_pszClipBeginMarkerName,
- pElement->m_pszClipBeginExternalMarkerFileName);
- if (SUCCEEDED(rc))
- {
- pElement->m_bClipBeginUsesMarker = TRUE;
- if (pElement->m_pszClipBeginExternalMarkerFileName)
- {
- pElement->m_bUsesExternalMediaMarkerFile = TRUE;
- // Add this element to the list
- if (!m_pClipBeginMarkerList)
- {
- m_pClipBeginMarkerList = new CHXSimpleList();
- }
- if (m_pClipBeginMarkerList)
- {
- m_pClipBeginMarkerList->AddTail((void*) pElement);
- }
- }
- }
- }
- else
- {
- rc = parseMarkerClipBeginEnd(pCh,
- pElement->m_pszClipEndMarkerName,
- pElement->m_pszClipEndExternalMarkerFileName);
- if (SUCCEEDED(rc))
- {
- pElement->m_bClipEndUsesMarker = TRUE;
- if (pElement->m_pszClipEndExternalMarkerFileName)
- {
- pElement->m_bUsesExternalMediaMarkerFile = TRUE;
- // Add this element to the list
- if (!m_pClipEndMarkerList)
- {
- m_pClipEndMarkerList = new CHXSimpleList();
- }
- if (m_pClipEndMarkerList)
- {
- m_pClipEndMarkerList->AddTail((void*) pElement);
- }
- }
- }
- }
- }
- else if (strcmp(pCh, "media") == 0)
- {
- if(nTag == SMILSyncAttrMin)
- {
- pElement->m_bUseMediaDurForMinDur = TRUE;
- }
- else if(nTag == SMILSyncAttrMax)
- {
- pElement->m_bUseMediaDurForMaxDur = TRUE;
- }
- }
- else
- {
- UINT32 ulClockValue = 0;
- // /First, see if this is pointing to a child id:
- // Don't waste time if it doesn't start with alpha char, '_', or ':'
- BOOL bHandled = FALSE;
- if (':' == *pCh || '_' == *pCh || isalpha(*pCh) )
- {
- if (HXR_OK == parseSmil1SyncbaseValue(pCh, pElement, nTag))
- {
- bHandled = TRUE;
- }
- }
- if(!bHandled)
- {
- if (HXR_OK == parseClockValue(pCh, ulClockValue))
- {
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_lBeginOffset = (INT32)ulClockValue;
- pElement->m_bBeginOffsetSet = TRUE;
- // /This needs to be handled here for time containers:
- pElement->m_bCurBeginIsOffsetFromSyncBase = TRUE;
- pElement->m_ulBeginOffsetFromSyncBase =
- pElement->m_lBeginOffset;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_lEndOffset = (INT32)ulClockValue;
- pElement->m_bEndOffsetSet = TRUE;
- }
- break;
- case SMILSyncAttrDur:
- {
- pElement->m_ulDuration = ulClockValue;
- }
- break;
- case SMILSyncAttrMin:
- {
- // /Spec says that, if min>max, we should ignore
- // both of their values:
- if (pElement->m_ulMaxActiveDur != ((UINT32)-1) &&
- pElement->m_ulMaxActiveDur < ulClockValue)
- {
- // /Reset max to essentially indefinite:
- pElement->m_ulMaxActiveDur = ((UINT32)-1);
- }
- else // /OK to set min:
- {
- pElement->m_ulMinActiveDur = ulClockValue;
- }
- }
- break;
- case SMILSyncAttrMax:
- {
- // /Spec says that, if min>max, we should ignore
- // both of their values:
- if (pElement->m_ulMinActiveDur != 0 &&
- pElement->m_ulMinActiveDur > ulClockValue)
- {
- // /Reset min to 0:
- pElement->m_ulMinActiveDur = 0;
- }
- else // /OK to set max:
- {
- pElement->m_ulMaxActiveDur = ulClockValue;
- }
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_ulEndSync = ulClockValue;
- }
- break;
- case SMILSyncAttrClipBegin:
- {
- pElement->m_ulAuthoredClipBegin = ulClockValue;
- pElement->m_ulClipBegin = ulClockValue;
- }
- break;
- case SMILSyncAttrClipEnd:
- {
- pElement->m_ulClipEnd = ulClockValue;
- }
- break;
- case SMILSyncAttrSyncTolerance:
- {
- pElement->m_ulSyncTolerance = ulClockValue;
- }
- break;
- case SMILSyncAttrSyncToleranceDefault:
- {
- pElement->m_ulSyncToleranceDefault = ulClockValue;
- }
- break;
- default:
- break;
- }
- }
- else
- {
- rc = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pCh,
- pElement->m_pNode->m_ulTagStartLine);
- }
- }
- }
- return rc;
- }
- HX_RESULT CSmilParser::parseMarkerClipBeginEnd(const char* pszStr,
- REF(char*) rpszMarkerName,
- REF(char*) rpszExtFileName)
- {
- HX_RESULT retVal = HXR_OK;
- if (pszStr)
- {
- // Parse the marker
- CHXString cMarker;
- CHXString cExtFileName;
- BOOL bIsExternal = FALSE;
- retVal = parseMarkerURI(pszStr, cMarker, bIsExternal, cExtFileName);
- if (SUCCEEDED(retVal))
- {
- // Copy the marker name
- HX_VECTOR_DELETE(rpszMarkerName);
- rpszMarkerName = new char [cMarker.GetLength() + 1];
- if (rpszMarkerName)
- {
- strcpy(rpszMarkerName, cMarker); /* Flawfinder: ignore */
- // If the marker is external, then copy the external file name
- if (bIsExternal)
- {
- HX_VECTOR_DELETE(rpszExtFileName);
- rpszExtFileName = new char [cExtFileName.GetLength() + 1];
- if (rpszExtFileName)
- {
- // Copy the string
- strcpy(rpszExtFileName, cExtFileName); /* Flawfinder: ignore */
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- return retVal;
- }
- HX_RESULT
- CSmilParser::adjustDuration(CSmilElement* pElement)
- {
- HX_RESULT rc = HXR_OK;
- // check for duration errors
- if(pElement->m_bEndOffsetSet)
- {
- // /We weren't taking MIN(end-b, dur) as we should in the case where
- // there is no begin offset set. So, <ref dur="5s" end="8s"/> now
- // plays for 5s but used to play for 8s, while adding begin="0s" to
- // that *did* work before (and still does):
- LONG32 lBeginOffset = 0;
- if(pElement->m_bBeginOffsetSet)
- {
- lBeginOffset = pElement->m_lBeginOffset;
- }
- if (!pElement->m_bIndefiniteBegin) // /Else all this is moot.
- {
- if(pElement->m_lEndOffset <
- pElement->m_lBeginOffset)
- {
- pElement->m_ulDuration = 0;
- goto exit;
- }
- if(pElement->m_ulDuration != (UINT32)-1)
- {
- if((INT32)pElement->m_ulDuration !=
- pElement->m_lEndOffset -
- pElement->m_lBeginOffset)
- {
- // If the element has both an explicit dur and an explicit
- // end, the desired end is the minimum of: the sum of the
- // desired begin and the explicit dur; and the explicit end.
- // override "dur"
- if (pElement->m_lBeginOffset + (INT32)pElement->m_ulDuration >
- pElement->m_lEndOffset)
- {
- // we want to override the duration, because it is
- // greater than the end offset.
- INT32 offset = pElement->m_lEndOffset -
- pElement->m_lBeginOffset;
- pElement->m_ulDuration = (offset >= 0 ? (UINT32)offset: 0);
- }
- else
- {
- // else we want to use the current duration,
- // and override the end offset.
- pElement->m_lEndOffset = pElement->m_lBeginOffset
- + pElement->m_ulDuration;
- }
- goto exit;
- }
- }
- }
- else // /No valid begin offset
- {
- HX_ASSERT(0 && "ehodge: can't adjust dur when begin is indef");
- #if defined(XXXEH_REMOVE_THIS_IF_TESTING_PROVES_OK_TO)
- if(pElement->m_ulDuration != (UINT32)-1)
- {
- if(pElement->m_lEndOffset <
- (INT32)pElement->m_ulDuration)
- {
- pElement->m_ulDuration = (pElement->m_lEndOffset >= 0 ?
- (UINT32)pElement->m_lEndOffset: 0);
- goto exit;
- }
- }
- #endif
- }
- }
- // adjust for begin/end/dur attributes
- if(pElement->m_ulDuration == (UINT32)-1) // duration not set
- {
- if(pElement->m_bEndOffsetSet)
- {
- // has an end but no duration
- if(pElement->m_bBeginOffsetSet)
- {
- // /We need to do the following to protect from the case
- // where (end-begin) overflows LONG32 val and otherwise
- // results in a bad duration value:
- double dEndOffset = (double)
- ((float)pElement->m_lEndOffset);
- double dBeginOffset = (double)
- ((float)pElement->m_lBeginOffset);
- double diff = dEndOffset - dBeginOffset;
- BOOL bDurationTooLarge = (diff > 0x7FFFFFFF);
- if (bDurationTooLarge)
- {
- // /XXXEH- TODO: figure out a way to have a longer
- // duration than 23 days (as in SMIL 2.0 Interop
- // Timing test #26.1):
- if (dBeginOffset < 0 &&
- pElement->m_lEndOffset<WAY_IN_THE_FUTURE)
- {
- pElement->m_ulDuration = pElement->m_lEndOffset;
- // /Now, we'll use negative begin as our clip-begin
- // and then set the begin to 0:
- if ((UINT32)-1 == pElement->m_ulClipBegin)
- {
- pElement->m_ulClipBegin =
- (UINT32)(-pElement->m_lBeginOffset);
- }
- else // /Add to it:
- {
- pElement->m_ulClipBegin -=
- pElement->m_lBeginOffset;
- }
- pElement->m_lBeginOffset = 0;
- }
- else
- {
- pElement->m_ulDuration = WAY_IN_THE_FUTURE;
- }
- }
- else
- {
- pElement->m_ulDuration = (pElement->m_lEndOffset -
- pElement->m_lBeginOffset >= 0 ?
- (UINT32)(pElement->m_lEndOffset -
- pElement->m_lBeginOffset): 0);
- }
- }
- else
- {
- pElement->m_ulDuration = (pElement->m_lEndOffset >= 0 ?
- (UINT32)pElement->m_lEndOffset: 0);
- }
- }
- }
- else // explicit duration set
- {
- if(pElement->m_bEndOffsetSet)
- {
- // has a duration and an end
- UINT32 ulDur = 0;
- if(pElement->m_bBeginOffsetSet)
- {
- ulDur = (pElement->m_lEndOffset -
- pElement->m_lBeginOffset >= 0 ?
- (UINT32)(pElement->m_lEndOffset -
- pElement->m_lBeginOffset): 0);
- }
- else
- {
- ulDur = (pElement->m_lEndOffset >= 0 ?
- (UINT32)pElement->m_lEndOffset: 0);
- }
- pElement->m_ulDuration = ulDur;
- }
- }
- exit:
- return rc;
- }
- void
- CSmilParser::badAttributeError(SMILNodeTag tag, const char* pAttrName,
- UINT32 ulLineNumber, BOOL bJustStore)
- {
- const char* pTagName = "unknown";
- // get tag name from table
- int i = 0;
- SMILNodeTag thisTag = SmilTagTable[i].m_tag;
- while(thisTag != SMILUnknown)
- {
- if(thisTag == tag)
- {
- pTagName = SmilTagTable[i].m_name;
- break;
- }
- ++i;
- thisTag = SmilTagTable[i].m_tag;
- }
- char tmpBuf[256]; /* Flawfinder: ignore */
- SafeSprintf(tmpBuf, 256, "<%s>: %s",
- pTagName, pAttrName);
- if (m_bStoreErrors)
- {
- storeError(SMILErrorUnrecognizedAttribute, tmpBuf, 0,
- ulLineNumber, 0, FALSE);
- }
- if (!bJustStore)
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnrecognizedAttribute, tmpBuf, ulLineNumber);
- }
- }
- CSmilMeta*
- CSmilParser::makeMeta(SMILNode* pNode)
- {
- CSmilMeta* pMeta = new CSmilMeta(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- SMIL2Attribute eAttr = getSMIL2Attribute(pName);
- switch(eAttr)
- {
- case SMIL2AttrName:
- {
- pMeta->m_name = (const char*)pBuf->GetBuffer();
- }
- break;
- case SMIL2AttrContent:
- {
- pMeta->m_content = (const char*)pBuf->GetBuffer();
- }
- break;
- }
- HX_RELEASE(pBuf);
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- HX_RELEASE(pBuf);
- // check for 'base'
- if(pMeta->m_name == "base")
- {
- HX_DELETE(m_pBasePath);
- m_pBasePath = new_string((const char*)pMeta->m_content);
- HX_RELEASE(pBuf);
- }
- }
- return pMeta;
- }
- CSmilMetadata*
- CSmilParser::makeMetadata(SMILNode* pNode)
- {
- CSmilMetadata* pMetadata = new CSmilMetadata(pNode);
- return pMetadata;
- }
- CSmilRendererPreFetch*
- CSmilParser::makeRendererPreFetch(SMILNode* pNode)
- {
- CSmilRendererPreFetch* pRenderer =
- new CSmilRendererPreFetch(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "type") == 0)
- {
- pRenderer->m_mimeType = (const char*)pBuf->GetBuffer();
- }
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- return pRenderer;
- }
- CSmilRootLayout*
- CSmilParser::makeRootLayout(SMILNode* pNode)
- {
- CSmilRootLayout* pRoot = NULL;
- HX_RESULT retVal = HXR_OK;
- if (pNode && pNode->m_pValues)
- {
- if (!m_bSMILRootLayoutAlreadyFound)
- {
- pRoot = new CSmilRootLayout(pNode);
- if (pRoot)
- {
- BOOL bFoundBGColor = FALSE;
- const char* pName = NULL;
- IHXBuffer* pBuf = NULL;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(SUCCEEDED(rc) && SUCCEEDED(retVal))
- {
- const char* pszValue =
- NULL!=pBuf?(const char*) pBuf->GetBuffer():NULL;
- // Check if the attribute is a legal namespaced attribute
- const char* pszNSAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pName, pszNSAttr);
- SMIL2Attribute eAttr = getSMIL2Attribute(pName);
- switch (eAttr)
- {
- case SMIL2AttrWidth:
- {
- retVal = parseRegionDimension(pszValue,
- pRoot->m_dWidth,
- pRoot->m_eWidthType);
- }
- break;
- case SMIL2AttrHeight:
- {
- retVal = parseRegionDimension(pszValue,
- pRoot->m_dHeight,
- pRoot->m_eHeightType);
- }
- break;
- case SMIL2AttrBackgroundColor:
- {
- bFoundBGColor = TRUE;
- retVal = parseColor(pszValue,
- pRoot->m_ulBackgroundColor,
- pRoot->m_eBackgroundColorType);
- }
- break;
- default:
- {
- if (!strcmp(pName, "background-color"))
- {
- // This check makes the parse prefer backgroundColor over
- // background-color if both are present
- if (!bFoundBGColor)
- {
- retVal = parseColor(pszValue,
- pRoot->m_ulBackgroundColor,
- pRoot->m_eBackgroundColorType);
- }
- }
- else if (pNSInfo && pszNSAttr &&
- (pNSInfo->m_eNamespace == NamespaceSizeControl ||
- pNSInfo->m_eNamespace == NamespaceSendTo ||
- pNSInfo->m_eNamespace == NamespaceAllSMIL2Extensions))
- {
- if (!strcmp(pszNSAttr, "resizeBehavior"))
- {
- if (!strcmp(pszValue, "zoom"))
- {
- pRoot->m_eResizeBehavior = ResizeZoom;
- }
- else if (!strcmp(pszValue, "percentOnly"))
- {
- pRoot->m_eResizeBehavior = ResizePercentOnly;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else if (!strcmp(pszNSAttr, "contextWindow"))
- {
- if (!strcmp(pszValue, "auto"))
- {
- pRoot->m_eContextWindow = ContextWindowAuto;
- }
- else if (!strcmp(pszValue, "openAtStart"))
- {
- pRoot->m_eContextWindow = ContextWindowOpenAtStart;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- }
- }
- if (FAILED(retVal))
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pszValue,
- pNode->m_ulTagStartLine);
- }
- HX_RELEASE(pBuf);
- if (SUCCEEDED(retVal))
- {
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnexpectedTag,
- (const char*) pNode->m_name,
- pNode->m_ulTagStartLine);
- retVal = HXR_FAIL;
- }
- }
- if (SUCCEEDED(retVal))
- {
- m_bSMILRootLayoutAlreadyFound = TRUE;
- }
- else
- {
- HX_DELETE(pRoot);
- }
- return pRoot;
- }
- CSmilRegion*
- CSmilParser::makeRegion(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- CSmilRegion* pRegion = NULL;
- if (pNode && pNode->m_pValues)
- {
- pRegion = new CSmilRegion(pNode);
- if (pRegion)
- {
- BOOL bParsedBGColor = FALSE;
- BOOL bParsedOpacity = FALSE;
- BOOL bGotNewStyleBG = FALSE;
- UINT32 ulOpacity = 0;
- const char* pName = NULL;
- IHXBuffer* pBuf = NULL;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(SUCCEEDED(rc) && SUCCEEDED(retVal))
- {
- // Get the attribute value
- const char* pszValue =
- NULL!=pBuf?(const char*) pBuf->GetBuffer():NULL;
- // Map the attribute name
- SMIL2Attribute eAttr = getSMIL2Attribute(pName);
- switch (eAttr)
- {
- case SMIL2AttrLeft:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dLeft,
- pRegion->m_Rect.m_eLeftType);
- }
- break;
- case SMIL2AttrTop:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dTop,
- pRegion->m_Rect.m_eTopType);
- }
- break;
- case SMIL2AttrRight:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dRight,
- pRegion->m_Rect.m_eRightType);
- }
- break;
- case SMIL2AttrBottom:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dBottom,
- pRegion->m_Rect.m_eBottomType);
- }
- break;
- case SMIL2AttrWidth:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dWidth,
- pRegion->m_Rect.m_eWidthType);
- }
- break;
- case SMIL2AttrHeight:
- {
- retVal = parseRegionDimension(pszValue,
- pRegion->m_Rect.m_dHeight,
- pRegion->m_Rect.m_eHeightType);
- }
- break;
- case SMIL2AttrZ_Index:
- {
- retVal = parseZIndex(pszValue,
- pRegion->m_lZIndex,
- pRegion->m_eZIndexType);
- }
- break;
- case SMIL2AttrFit:
- {
- retVal = parseFit(pszValue, pRegion->m_eFit);
- }
- break;
- case SMIL2AttrShowBackground:
- {
- if (!strcmp(pszValue, "always"))
- {
- pRegion->m_eShowBackground = ShowBackgroundAlways;
- }
- else if (!strcmp(pszValue, "whenActive"))
- {
- pRegion->m_eShowBackground = ShowBackgroundWhenActive;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2AttrSoundLevel:
- {
- char* pEndPtr = NULL;
- double dVal = strtod(pszValue, &pEndPtr);
- if (pEndPtr && *pEndPtr == '%')
- {
- pRegion->m_dSoundLevel = dVal;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2AttrRegionName:
- {
- pRegion->m_RegionName = pszValue;
- pRegion->m_bRegionNameSpecified = TRUE;
- }
- break;
- case SMIL2AttrBackgroundColor:
- {
- // Get the background color
- retVal = parseColor(pszValue,
- pRegion->m_ulBackgroundColor,
- pRegion->m_eBackgroundColorType);
- if (SUCCEEDED(retVal))
- {
- bParsedBGColor = TRUE;
- bGotNewStyleBG = TRUE;
- }
- }
- break;
- default:
- {
- if (strcmp(pName, "background-color") == 0 &&
- !bGotNewStyleBG)
- {
- // Get the background color
- retVal = parseColor(pszValue,
- pRegion->m_ulBackgroundColor,
- pRegion->m_eBackgroundColorType);
- if (SUCCEEDED(retVal))
- {
- bParsedBGColor = TRUE;
- }
- }
- else
- {
- // Check if the attribute is a legal namespaced attribute
- const char* pszNSAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pName, pszNSAttr);
- if (pNSInfo)
- {
- if (pNSInfo->m_eNamespace == NamespaceAlphaControl ||
- pNSInfo->m_eNamespace == NamespaceAllSMIL2Extensions)
- {
- if(!strcmp(pszNSAttr, "opacity"))
- {
- // Parse the opacity
- retVal = parseOpacity(pszValue, ulOpacity);
- if (SUCCEEDED(retVal))
- {
- bParsedOpacity = TRUE;
- }
- }
- }
- }
- }
- }
- }
- HX_RELEASE(pBuf);
- if (SUCCEEDED(retVal))
- {
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- else
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pRegion->m_pNode->m_ulTagStartLine);
- }
- }
- if (SUCCEEDED(retVal))
- {
- // Compute alpha from opacity - the value
- // coming out of parseOpacity() is guaranteed to
- // be in the range [0,255]
- UINT32 ulAlpha = 255 - ulOpacity;
- // Process the opacity and background color. By default,
- // m_ulBackgroundColor = 0xFF000000 (transparent). Here are
- // the four cases:
- //
- // 1) Both backgroundColor and rn:opacity are specified - we
- // should use the RRGGBB from parseColor and the opacity
- // value from rn:opacity
- // 2) backgroundColor is specified, but rn:opacity is not.
- // The resulting color must be opaque in order to be
- // backwards-compatible. Since parseColor() puts in 0x00
- // for the alpha channel (opaque), then we don't have to
- // do anything here.
- // 3) rn:opacity was specified, but backgroundColor was not.
- // Kinda unclear what to do here, since the backgroundColor
- // default is "transparent", but I will take this to mean
- // that the author wants this to be "partially transparent".
- // So we will use the alpha from opacity and put "#000000"
- // (black) for the color. We just as easily chould use
- // "#FFFFFF" (white).
- // 4) Neither backgroundColor nor rn:opacity was specified.
- // We have to go with the default of backgroundColor, which
- // is "transparent".
- if (bParsedBGColor)
- {
- if (bParsedOpacity)
- {
- // Both backgroundColor and rn:opacity are specified
- pRegion->m_ulBackgroundColor = (pRegion->m_ulBackgroundColor & 0x00FFFFFF) |
- (ulAlpha << 24);
- }
- else
- {
- // backgroundColor is specified but not rn:opacity. So for
- // backwards-compatibility, the resulting color must be
- // opaque. So zero out the alpha channel of the color.
- // We really shouldn't have to do this, since parseColor
- // generally puts 0x00 in the alpha, but we force it here
- // "just to be sure".
- // The only exception to this rule is if the
- // backgroundColor is explicity specified as
- // backgroundColor="transparent"
- if (pRegion->m_eBackgroundColorType != CSS2TypeTransparent)
- {
- pRegion->m_ulBackgroundColor &= 0x00FFFFFF;
- }
- }
- }
- else
- {
- if (bParsedOpacity)
- {
- // rn:opacity was specified, but not backgroundColor, so
- // we need to insert the alpha value into the backgroundColor
- // We will let the color be #000000.
- pRegion->m_ulBackgroundColor = (ulAlpha << 24);
- }
- else
- {
- // Neither rn:opacity was specified nor backgroundColor, so
- // we must take the backgroundColor default, which is "transparent".
- // We really should not have to do anything here, since the
- // default of m_ulBackgroundColor in the constructor is 0xFF000000.
- // However, we set it here "just to be sure".
- pRegion->m_ulBackgroundColor = 0xFF000000;
- }
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pRegion);
- }
- return pRegion;
- }
- CSmilRegPoint*
- CSmilParser::makeRegPoint(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- CSmilRegPoint* pRegPt = NULL;
- if (pNode && pNode->m_pValues)
- {
- pRegPt = new CSmilRegPoint(pNode);
- if (pRegPt)
- {
- const char* pName = NULL;
- IHXBuffer* pBuf = NULL;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(SUCCEEDED(rc) && SUCCEEDED(retVal))
- {
- // Get the attribute value
- const char* pszValue =
- NULL!=pBuf?(const char*) pBuf->GetBuffer():NULL;
- // Get the SMIL2Attribute
- SMIL2Attribute eAttr = getSMIL2Attribute(pName);
- switch (eAttr)
- {
- case SMIL2AttrLeft:
- {
- retVal = parseRegionDimension(pszValue,
- pRegPt->m_RegPoint.m_dLeft,
- pRegPt->m_RegPoint.m_eLeftType);
- }
- break;
- case SMIL2AttrTop:
- {
- retVal = parseRegionDimension(pszValue,
- pRegPt->m_RegPoint.m_dTop,
- pRegPt->m_RegPoint.m_eTopType);
- }
- break;
- case SMIL2AttrRight:
- {
- retVal = parseRegionDimension(pszValue,
- pRegPt->m_RegPoint.m_dRight,
- pRegPt->m_RegPoint.m_eRightType);
- }
- break;
- case SMIL2AttrBottom:
- {
- retVal = parseRegionDimension(pszValue,
- pRegPt->m_RegPoint.m_dBottom,
- pRegPt->m_RegPoint.m_eBottomType);
- }
- break;
- case SMIL2AttrRegAlign:
- {
- retVal = parseRegAlign(pszValue, pRegPt->m_RegPoint.m_eRegAlign);
- }
- break;
- }
- HX_RELEASE(pBuf);
- if (SUCCEEDED(retVal))
- {
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- else
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pRegPt->m_pNode->m_ulTagStartLine);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pRegPt);
- }
- return pRegPt;
- }
- #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
- CSmilViewport*
- CSmilParser::makeViewport(SMILNode* pNode)
- {
- HX_RESULT retVal = HXR_OK;
- CSmilViewport* pView = NULL;
- if (pNode && pNode->m_pValues)
- {
- pView = new CSmilViewport(pNode);
- if (pView)
- {
- BOOL bOldStyleBG = FALSE;
- const char* pName = NULL;
- IHXBuffer* pBuf = NULL;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(SUCCEEDED(rc) && SUCCEEDED(retVal))
- {
- // Get the attribute value
- const char* pszValue =
- NULL!=pBuf?(const char*) pBuf->GetBuffer():NULL;
- // Check if the attribute is a legal namespaced attribute
- const char* pszNSAttr = NULL;
- CNamespaceInfo* pNSInfo = getNamespaceInfo(pName, pszNSAttr);
- // Get the SMIL2Attribute
- SMIL2Attribute eAttr = getSMIL2Attribute(pName);
- switch (eAttr)
- {
- case SMIL2AttrWidth:
- {
- retVal = parseRegionDimension(pszValue,
- pView->m_dWidth,
- pView->m_eWidthType);
- }
- break;
- case SMIL2AttrHeight:
- {
- retVal = parseRegionDimension(pszValue,
- pView->m_dHeight,
- pView->m_eHeightType);
- }
- break;
- case SMIL2AttrBackgroundColor:
- {
- retVal = parseColor(pszValue,
- pView->m_ulBackgroundColor,
- pView->m_eBackgroundColorType);
- }
- break;
- case SMIL2AttrOpen:
- {
- if (!strcmp(pszValue, "onStart"))
- {
- pView->m_eOpen = ViewportOpenOnStart;
- }
- else if (!strcmp(pszValue, "whenActive"))
- {
- pView->m_eOpen = ViewportOpenWhenActive;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- case SMIL2AttrClose:
- {
- if (!strcmp(pszValue, "onRequest"))
- {
- pView->m_eClose = ViewportCloseOnRequest;
- }
- else if(!strcmp(pszValue, "whenNotActive"))
- {
- pView->m_eClose = ViewportCloseWhenNotActive;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- break;
- default:
- {
- if (!strcmp(pName, "background-color") &&
- !bOldStyleBG)
- {
- retVal = parseColor(pszValue,
- pView->m_ulBackgroundColor,
- pView->m_eBackgroundColorType);
- }
- else if (pNSInfo && pszNSAttr &&
- (pNSInfo->m_eNamespace == NamespaceSizeControl ||
- pNSInfo->m_eNamespace == NamespaceSendTo ||
- pNSInfo->m_eNamespace == NamespaceAllSMIL2Extensions))
- {
- if (!strcmp(pszNSAttr, "resizeBehavior"))
- {
- if (!strcmp(pszValue, "zoom"))
- {
- pView->m_eResizeBehavior = ResizeZoom;
- }
- else if (!strcmp(pszValue, "percentOnly"))
- {
- pView->m_eResizeBehavior = ResizePercentOnly;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- else if (!strcmp(pszNSAttr, "contextWindow"))
- {
- if (!strcmp(pszValue, "auto"))
- {
- pView->m_eContextWindow = ContextWindowAuto;
- }
- else if (!strcmp(pszValue, "openAtStart"))
- {
- pView->m_eContextWindow = ContextWindowOpenAtStart;
- }
- else
- {
- retVal = HXR_FAIL;
- }
- }
- }
- }
- }
- HX_RELEASE(pBuf);
- if (SUCCEEDED(retVal))
- {
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- else
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pView->m_pNode->m_ulTagStartLine);
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_FAIL;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pView);
- }
- return pView;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
- CSmilCustomTest*
- CSmilParser::makeCustomTest(SMILNode* pNode, REF(HX_RESULT) retVal)
- {
- retVal = HXR_OK;
- CSmilCustomTest* pCustomTest = NULL;
- if (pNode && pNode->m_pValues)
- {
- pCustomTest = new CSmilCustomTest(pNode);
- if (pCustomTest)
- {
- const char* pName = NULL;
- IHXBuffer* pBuf = NULL;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(
- pName, pBuf);
- while(SUCCEEDED(rc) && SUCCEEDED(retVal))
- {
- // Get the attribute value
- const char* pszValue =
- NULL!=pBuf?(const char*) pBuf->GetBuffer():NULL;
- if (pszValue)
- {
- const char* pWhitespaceRemoved =
- removeSurroundingWhitespace(pszValue);
- // Parse the attribute value
- if (0 == strcmp(pName, "defaultState"))
- {
- if (!strcmp(pWhitespaceRemoved, "true"))
- {
- pCustomTest->m_bDefaultState = TRUE;
- }
- else if (!strcmp(pWhitespaceRemoved, "false"))
- {
- pCustomTest->m_bDefaultState = FALSE;
- }
- else
- {
- retVal = HXR_INVALID_PARAMETER;
- }
- }
- else if (0 == strcmp(pName, "override"))
- {
- if (!strcmp(pWhitespaceRemoved, "visible"))
- {
- pCustomTest->m_bOverrideVisible = TRUE;
- }
- else if (!strcmp(pWhitespaceRemoved, "hidden"))
- {
- pCustomTest->m_bOverrideVisible = FALSE;
- }
- else
- {
- retVal = HXR_INVALID_PARAMETER;
- }
- }
- else if (0 == strcmp(pName, "uid"))
- {
- pCustomTest->m_uid = pWhitespaceRemoved;
- }
- HX_RELEASE(pBuf);
- if (SUCCEEDED(retVal))
- {
- rc = pNode->m_pValues->GetNextPropertyCString(
- pName, pBuf);
- }
- else
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- pName,
- pCustomTest->m_pNode->m_ulTagStartLine);
- }
- }
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_UNEXPECTED;
- }
- if (FAILED(retVal))
- {
- HX_DELETE(pCustomTest);
- }
- return pCustomTest;
- }
- HX_RESULT
- CSmilParser::parseCoord(IHXBuffer* pBuf, REF(float) f)
- {
- HX_RESULT ret = HXR_OK;
- double d = 0.0;
- ret = HXParseDouble((const char*)pBuf->GetBuffer(), d);
- if (d < -2.0 ||
- d > 2.0)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- else
- {
- f = (float)d;
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::parseDigit(IHXBuffer* pBuf, REF(UINT32) ul)
- {
- HX_RESULT ret = HXR_OK;
- INT32 num = 0;
- ret = HXParseDigit((const char*)pBuf->GetBuffer(), num);
- if (num < 0)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- else
- {
- ul = (UINT32)num;
- }
- return ret;
- }
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- CSmilTransition* CSmilParser::makeTransition(SMILNode* pNode, REF(HX_RESULT) retVal)
- {
- // Initialize the error out parameter
- retVal = HXR_OK;
- // Initialize the return value
- CSmilTransition* pTrans = NULL;
- // Initialize our flags
- BOOL bTypePresent = FALSE;
- BOOL bTypeLegal = FALSE;
- BOOL bSubTypePresent = FALSE;
- BOOL bSubTypeLegal = FALSE;
- // Make sure we have a node
- if (pNode && pNode->m_pValues)
- {
- // Create a CSmilTransition class
- pTrans = new CSmilTransition(pNode);
- if (pTrans)
- {