smltime.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:225k
源码类别:

Symbian

开发平台:

Visual C++

  1. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2. {
  3.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  4. }
  5. if (HXR_OK !=
  6. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  7. {
  8.     goto doneSettingDependent;
  9. }
  10. #else
  11. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  12. m_pSourceElement->m_ulDuration;
  13. // /Helps fix PR 6XXXX(media version): if delay is already packed
  14. // into the duration, then don't count it twice (as can happen in
  15. // <seq><ref begin="1s" .../><ref begin="1s" .../>...):
  16. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  17. {
  18.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  19. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
  20.     {
  21. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  22. ulTotalDelay);
  23. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  24. ulTotalDelay)
  25. {
  26.     ulTotalDelay -=
  27.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  28. }
  29.     }
  30. }
  31. #endif
  32. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  33. {
  34.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  35.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  36. }
  37.  
  38. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  39.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  40.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  41.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  42.     ::fprintf(f1, "nt%s:CSmilTimelinePar::resetDelay(%lu):from %lu to %lu;"
  43.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  44.     ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
  45.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  46.     ::fclose(f1); 
  47.     bFirstTimeAddDurDebugout = FALSE; 
  48. #endif 
  49.  
  50. m_pDependent->resetDelay(ulTotalDelay);
  51. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  52. doneSettingDependent:
  53. #endif
  54. // /(Added while fixing PR 59851) Let others know our begin time changed:
  55. m_pParser->m_pTimelineElementManager->notify(m_pID);
  56.     }
  57. }
  58. void 
  59. CSmilTimelinePar::adjustDuration()
  60. {
  61.     BOOL    bReset = FALSE;
  62.     UINT32  ulDuration = 0;
  63.     BOOL    bDurationSet = FALSE;
  64.     BOOL    bEndsyncIdDurationFound = FALSE; // /For endsync="[Some ID]"
  65.     // /Need this for fixing PR 50676 part 6:
  66.     ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  67.     if (!m_bDurationSet)
  68.     {
  69. goto cleanup;
  70.     }
  71.     if(m_pChildren)
  72.     {
  73. CHXSimpleList::Iterator i = m_pChildren->Begin();
  74. for(; i != m_pChildren->End(); ++i)
  75. {
  76.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  77.     // /Checking this fixes PR 69290: if child duration wasn't set,
  78.     // then for crying out loud don't use it here:
  79.     if (!pElement->m_bDurationSet)
  80.     {
  81. continue;
  82.     }
  83.     HX_ASSERT((UINT32)-1 != pElement->m_pSourceElement->m_ulDuration);
  84.     // /Make sure we take endsync into account here; doing so helps fix
  85.     // PR 50679 (and probably other bugs):
  86.     if (SMILEventSourceFirst == m_pSourceElement->m_nEndsyncEventSourceTag)
  87.     {
  88. if (!bDurationSet)
  89. {
  90.     ulDuration = pElement->m_pSourceElement->m_ulDuration;
  91. }
  92. else
  93. {
  94.          ulDuration = (ulDuration < pElement->m_pSourceElement->m_ulDuration) ?
  95.     ulDuration : pElement->m_pSourceElement->m_ulDuration;
  96. }
  97. bDurationSet = TRUE;
  98.     }
  99.     else if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
  100.     {
  101. if (pElement->m_pSourceElement->m_pNode  &&
  102. m_pSourceElement->m_EndsyncEventSourceID ==
  103. pElement->m_pSourceElement->m_pNode->m_id)
  104. {
  105.     ulDuration = pElement->m_pSourceElement->m_ulDuration;
  106.     bEndsyncIdDurationFound = TRUE;
  107.     bDurationSet = TRUE;
  108. }
  109.     }
  110.     // /This else-if block fixes problem in PR 62688 repro case where
  111.     // restarting a child, prior to all children playing, caused excl
  112.     // to resolve its dur as if it were endsync="last":
  113.     else if (SMILEventSourceAll ==
  114.     m_pSourceElement->m_nEndsyncEventSourceTag)
  115.     {
  116. if (m_pChildren  &&
  117. m_nDurationAdded >= m_pChildren->GetCount())
  118. {
  119.          ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
  120.     ulDuration : pElement->m_pSourceElement->m_ulDuration;
  121.     bDurationSet = TRUE;
  122. }
  123. else
  124. {
  125.     // /Don't adjust duration until all child durs are in:
  126.     goto cleanup;
  127. }
  128.     }
  129.     else // /For "last", use the largest child duration:
  130.     {
  131. ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
  132. ulDuration : pElement->m_pSourceElement->m_ulDuration;
  133. bDurationSet = TRUE;
  134.     }
  135.     // /Fixes PR 50806 (original par version, INTEROP Timing #23.6 as
  136.     // well as par version 2 (endsync="last")): if this has a "min"
  137.     // attribute set, ulDuration shouldn't be less regardless of endSync:
  138.     if (m_pSourceElement->m_ulMinActiveDur > ulDuration)
  139.     {
  140. ulDuration = m_pSourceElement->m_ulMinActiveDur;
  141.     }
  142. }
  143. // /!bDurationSet happens in PR 50588 (case 2: begin="x.end"), when
  144. // child has begun playing but has not yet resolved its duration:
  145. if (!bDurationSet)
  146. {
  147.     goto cleanup;
  148. }
  149. if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
  150. {
  151.     if (!bEndsyncIdDurationFound)
  152.     {
  153. goto cleanup; // /That id'd child not added to timeline yet.
  154.     }
  155. }
  156. //check m_ulAuthoredDur here:
  157. if (!m_pSourceElement->m_bHasExplicitEnd  &&
  158. !m_pSourceElement->m_bHasExplicitDur)
  159. {
  160.     m_pSourceElement->m_ulDuration = ulDuration;
  161. }
  162.     
  163. // /Moved this out of the above if() so it gets called every time, to
  164. // fix PR 6XXX? and re-fix PR 55117: we should always give our parents
  165. // a chance to set the outer-time-container duration so it can (re)-
  166. // state to the core what the group duration should be:
  167. if(m_pParent)
  168. {
  169.     m_pParent->adjustDuration();
  170. }
  171. // /Moved this out to happen all the time, too:
  172. if (m_pDependent)
  173. {
  174. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  175.     ULONG32 ulTotalDelay = 0;
  176.     if (HXR_OK !=
  177.     m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  178.     {
  179. goto doneSettingDependent;
  180.     }
  181. #else
  182.     ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  183.     m_pSourceElement->m_ulDuration;
  184.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  185.     {
  186. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  187. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
  188. {
  189.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  190.     ulTotalDelay);
  191.     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  192.     ulTotalDelay)
  193.     {
  194. ulTotalDelay -=
  195. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  196.     }
  197. }
  198.     }
  199. #endif
  200.     if (WAY_IN_THE_FUTURE < ulTotalDelay)
  201.     {
  202. // /XXXEH- If delay is greater than this, I want to know:
  203. HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay);
  204. ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  205.     }
  206. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  207. {
  208.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  209.     ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  210.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  211.     ::fprintf(f1, "nt%s:CSmilTimelinePar::adjustDuration();tresetting dependent (%s)'s delay to %lun",
  212.     (const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
  213.     ::fclose(f1);
  214.     bFirstTimeAddDurDebugout = FALSE;
  215. }
  216. #endif
  217.     m_pDependent->resetDelay(ulTotalDelay);
  218. }
  219. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  220. doneSettingDependent:
  221. ;
  222. #endif
  223.     }
  224.     // /Fixes PR 69410 (with outer par): do this no matter what, even if
  225.     // prior < ulDur; resumed element in excl descendant should extend that
  226.     // excl but we've already told the core to limit the presentation
  227.     // duration, so extend it here as needed:
  228.     // /Helps fix PR 50676 part 6: if our duration got reduced, we need to
  229.     // possibly constrain our children:
  230.     {
  231. // /For PR 62688 & PR 59584: remove check for ulPriorDuration being
  232. // WAY_IN_THE_FUTURE since PR 50676 works without it and there are
  233. // cases where our dur may re-resolve, & updating children is needed.
  234. // /For PR 59584: the group's outer time container needs to set the
  235. // duration if its dur is longer than its group's so far:
  236. if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  237. {
  238.     if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  239.     m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  240.     m_pSourceElement->m_pNode->
  241.     m_pParent->m_bIsOuterWrapperTimeContainer) )
  242.     {
  243. BOOL bDoResolveGroupDur = TRUE;
  244. UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
  245. if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
  246. {
  247.     ulGroup = 0;
  248.     // /If we're outer wrapper around multiple groups
  249.     // (or "clips"), then let each group outer time container
  250.     // resolve its group duration:
  251.     if (m_pChildren->GetCount() > 1)
  252.     {
  253. bDoResolveGroupDur = FALSE;
  254.     }
  255. }
  256. if (bDoResolveGroupDur)
  257. {
  258.     // /The group duration should be the duration of this
  259.     // outer-most time container:
  260.     HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  261.     resolveGroupDurToOuterTimeContainerDur(
  262.     ulGroup, m_pSourceElement->m_ulDuration);
  263. }
  264.     }
  265. }
  266. if(m_pChildren)
  267. {
  268.     // /Accounting for begin offset of this helps fix PR 65741(par)
  269.     // where excl w/begin="5s' was including that 5s in dur passed
  270.     // to children, thus children were playing 5s too long:
  271.     ULONG32 ulSyncBaseDurationForChildren =
  272.     m_pSourceElement->m_ulDuration;
  273.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  274.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  275.     {
  276. HX_ASSERT(ulSyncBaseDurationForChildren >=
  277. m_pSourceElement->m_ulBeginOffsetFromSyncBase);
  278. if (ulSyncBaseDurationForChildren >=
  279. m_pSourceElement->m_ulBeginOffsetFromSyncBase)
  280. {
  281.     ulSyncBaseDurationForChildren -=
  282.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  283. }
  284.     }
  285.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  286.     for(; i != m_pChildren->End(); ++i)
  287.     {
  288. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  289. if (pElement->m_pSourceElement  &&
  290. pElement->m_pSourceElement->m_ulDuration >
  291. m_pSourceElement->m_ulDuration)
  292. {
  293.     pElement->setDuration(ulSyncBaseDurationForChildren, TRUE);
  294. }
  295.     }
  296. }
  297.     }
  298. cleanup:
  299.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  300.     return;
  301. }
  302. void 
  303. CSmilTimelinePar::addDuration(UINT32 ulDuration,
  304.       UINT32 ulDelay,
  305.       UINT32 ulChildDelayBeyondStartOfThis, 
  306.       const char* pElementID)
  307. {
  308.     BOOL bHandled = FALSE;
  309.     UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  310. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  311.     {
  312. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  313. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  314. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  315. ::fprintf(f1, "CSmilTimelinePar{%s}::addDuration(dur=%lu, delay=%lu, "
  316. "childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sEn",
  317. (const char*)m_pID, ulDuration, ulDelay,
  318. ulChildDelayBeyondStartOfThis, pElementID,
  319. m_bDurationSet?"TRU":"FALS");
  320. ::fclose(f1);
  321. bFirstTimeAddDurDebugout = FALSE;
  322.     }
  323. #endif
  324.     // /If we're inside a seq, our true "sync base" is not the seq but rather
  325.     // the prievious seq sibling (if any).  We need to adjust the ulDelay, if
  326.     // we're in a seq, down to just ulChildDelayBeyondStartOfThis, which is
  327.     // the delay from the prior sibling, not from the seq:
  328.     ULONG32 ulDelayBeyondSyncBase = 0;
  329.     SMILNode* pSyncBaseNode = NULL;
  330.     if (m_pSourceElement->m_pNode)
  331.     {
  332. pSyncBaseNode = m_pParser->getSyncAncestor(
  333.     m_pSourceElement->m_pNode);
  334.     }
  335.     if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
  336.     {
  337. HX_ASSERT(pSyncBaseNode  &&  pSyncBaseNode->m_pElement);
  338.     }
  339.     // /Do this for all time containers (for part of PR52110 post-fix-delay-
  340.     // offset-bug):
  341.     else
  342.     {
  343. ulDelayBeyondSyncBase = ulChildDelayBeyondStartOfThis;
  344.     }
  345.     BOOL bSetChildCurEndClippedByParent = FALSE;
  346.     BOOL bSetCompletelyRemovedFromTimeline = FALSE;
  347.     BOOL bIsCurChildsFirstAddDuration = FALSE;
  348.     ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
  349.     if (!(*m_pChildDurAddedMap)[pElementID])
  350.     {
  351. bIsCurChildsFirstAddDuration = TRUE;
  352.     }
  353.     else
  354.     {
  355. ulCurChildPriorAddedDuration =
  356. (ULONG32)((*m_pChildDurAddedMap)[pElementID]);
  357.     }
  358.     ULONG32 ulActualDurBeyondSyncBase =
  359.     ulDuration + ulDelayBeyondSyncBase - ulChildDelayBeyondStartOfThis;
  360. // /XXXEH-20020106-test:    HX_ASSERT(WAY_IN_THE_FUTURE >= ulActualDurBeyondSyncBase);
  361.     // /Start of fix for PR 55117: explicit dur or end on par should not be
  362.     // overridden by some punk child's dur; if this has an explicit
  363.     // end or dur, don't do anything to its duration based on children durs:
  364.     // /XXXEH- TODO: determine what wins between endsync VS either end or dur
  365.     // if both are specified; here, I assume end|dur wins over endsync:
  366.     if (m_pSourceElement->m_bHasExplicitDur  ||
  367.     m_pSourceElement->m_bHasExplicitEnd)
  368.     {
  369. if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
  370. (!m_bDurationSet  ||
  371. !m_pSourceElement->m_bAddDurationAlreadyDone) )
  372. {
  373.     HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  374.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  375.     m_pSourceElement->getPureDuration());
  376.     durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  377. }
  378. // /Helps fix PR 6XXXZ (PR 55117 revisited): par in seq where par has explicit dur and
  379. // children all have smaller durations, we need to give outer time
  380. // container a chance to hold the presentation open; this is needed
  381. // when this par is last one in presentation.  (Note: body doesn't set
  382. // the presentation time during createElements() phase because it
  383. // doesn't have m_pHandler yet then):
  384. adjustDuration();
  385. bHandled = TRUE;
  386.     }
  387.     // /Fixes SMIL 1.0's endsync="id(xyz)" and enables SMIL 2.0's
  388.     // id-based endsync: endsync="xyz":
  389.     else if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
  390.     {
  391. if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
  392.         !strcmp(m_pSourceElement->m_EndsyncEventSourceID,pElementID))
  393. {
  394.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  395.     m_pSourceElement->getPureDuration());
  396.     // /Don't just use ulDuration in case child has a begin offset
  397.     // or otherwise has a delay beyond this's delay.
  398.     m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
  399.     durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  400.     bHandled = TRUE;
  401. }
  402. // /Fixes endsync="[ID]" part of PR 59584 where addDuration of X (!=ID)
  403. // happens after that of lower-duration [ID] sibling and 'X' needs to
  404. // be restricted to ID's duration:
  405. else if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
  406.         m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
  407. {
  408.     // /Adjust for offset from parent, if any:
  409.     bSetChildCurEndClippedByParent = TRUE;
  410.     if (m_pSourceElement->m_ulDuration >
  411.     ulChildDelayBeyondStartOfThis)
  412.     {
  413. m_pParser->resetTimelineElementDuration(pElementID,
  414. m_pSourceElement->getPureDuration(),
  415. // /Changed to *child* prior dur while fixing PR 66391:
  416. ulActualDurBeyondSyncBase -
  417. ulChildDelayBeyondStartOfThis);
  418. m_pParser->m_pTimelineElementManager->notify(pElementID);
  419.     }
  420.     else // /Begin offset is beyond parent's end, so remove it:
  421.     // /Fixes PR 64158 (endsync="[ID]" version)
  422.     {
  423. bSetCompletelyRemovedFromTimeline = TRUE;
  424. HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  425. handleTrackRemoval((const char*)pElementID,
  426. (INT32)m_pSourceElement->m_pNode->m_nGroup);
  427.     }
  428. }
  429.     }
  430.     else if(m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceAll)
  431.     {
  432. // /Hold par open until all children have had a chance to begin;
  433. // leave the par's duration unresolved awaiting the final child's
  434. // call to "addDuration" (which may never come if child's begin
  435. // never resolves):
  436. // /Helps fix PR 62688(par version): first, check if all children
  437. // have resolved already; if so, then duration is set so we can't
  438. // extend it if begin is after parent par ended:
  439. if (m_nDurationAdded >= m_pChildren->GetCount()  &&
  440. m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
  441. {
  442.     bSetChildCurEndClippedByParent = TRUE;
  443.     HX_ASSERT(m_ulLastDuration == m_pSourceElement->m_ulDuration);
  444.     if (m_ulLastDuration > ulChildDelayBeyondStartOfThis)
  445.     {
  446. // /Helps fix PR 50660 by removing PR 62688-fix code here that
  447. // turned out to be unnecessary since code elsewhere completely
  448. // fixes PR 62688.  Child should be allowed to extend its
  449. // parent's duration except if it begins *after* its parent has
  450. // already ended, which is how we got here, so do nothing.
  451.     }
  452.     else // /Begin offset is beyond parent's end, so remove it:
  453.     // helps fix PR 62688(par) (endsync="all" version of PR 64158)
  454.     {
  455. bSetCompletelyRemovedFromTimeline = TRUE;
  456. HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  457. handleTrackRemoval((const char*)pElementID,
  458. (INT32)m_pSourceElement->m_pNode->m_nGroup);
  459.     }
  460. }
  461. if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
  462. !m_bFirstDurationHasBeenSet)
  463. {
  464.     m_ulFirstDuration = ulActualDurBeyondSyncBase;
  465.     m_bFirstDurationHasBeenSet = TRUE;
  466. }
  467. if(ulActualDurBeyondSyncBase > m_ulLastDuration)
  468. {
  469.     m_ulLastDuration = ulActualDurBeyondSyncBase;
  470. }
  471. // /This helps fix PR 62688(par version): this is used to see if
  472. // we've already resolved our duration (because all children have
  473. // weighed in):
  474. INT32 lTotalDurationsAddedIncludingThisOne = (INT32)m_nDurationAdded;
  475. if (bIsCurChildsFirstAddDuration)
  476. {
  477.     lTotalDurationsAddedIncludingThisOne++;
  478. }
  479. if (lTotalDurationsAddedIncludingThisOne < m_pChildren->GetCount()  &&
  480. // /To help fix PR 59584(par version), only do this once:
  481. WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
  482. {
  483.     // /XXXEH- need a better way, but for now let's say it's
  484.     // resolved to a very big number until all children have
  485.     // resolved begins:
  486.     durationResolved(WAY_IN_THE_FUTURE, TRUE);
  487. }
  488.     }
  489.     else if(m_pSourceElement->m_ulDuration == (UINT32)-1)
  490.     {
  491. // /Added delay to duration which works in:
  492. // "BUG-20010430_endHappening2sTooEarlyForExclThatHas"...
  493. // ..."2.7sBeginAndDurBasedOnChild(totalPresentationDur5.7s).smil":
  494. m_pSourceElement->m_ulDuration = ulDuration + ulDelayBeyondSyncBase -
  495. // /Added this to fix when par child of seq has child w/begin
  496. // offset, as in the following smil file:
  497. // "BUG-20010501_(broke20010501earlyAMCheckin)beginOnFirst"...
  498. ulChildDelayBeyondStartOfThis;
  499. m_ulFirstDuration = ulActualDurBeyondSyncBase;
  500. m_bFirstDurationHasBeenSet = TRUE;
  501. m_ulLastDuration = ulActualDurBeyondSyncBase;
  502.     }
  503.     else
  504.     {
  505. m_pSourceElement->m_ulDuration = 
  506.     (ulActualDurBeyondSyncBase > m_pSourceElement->m_ulDuration) ?
  507.     ulActualDurBeyondSyncBase : m_pSourceElement->m_ulDuration;
  508. if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
  509. // /Fixes several PRs related to endsync="first"; m_ulFirstDuration
  510. // gets init'd to 0, so we need to see if it's been set or not:
  511. !m_bFirstDurationHasBeenSet)
  512. {
  513.     m_ulFirstDuration = ulActualDurBeyondSyncBase;
  514.     m_bFirstDurationHasBeenSet = TRUE;
  515. }
  516. if(ulActualDurBeyondSyncBase > m_ulLastDuration)
  517. {
  518.     m_ulLastDuration = ulActualDurBeyondSyncBase;
  519. }
  520.     }
  521.     ULONG32 ulRevisedActualDurBeyondSyncBase = ulActualDurBeyondSyncBase;
  522.     if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceFirst)
  523.     {
  524. // /Helps fix PR 66391: if child is time container, make sure this's
  525. // duration is set to shortest child's duration:
  526. m_pSourceElement->m_ulDuration = m_ulFirstDuration;
  527. // /Fixes endsync="first" version of PR 64157 where addDuration
  528. // of longer vid happens after that of lower-duration sibling and
  529. // longer one needs to be clipped to that lower duration (or completely
  530. // removed if begin offset is beyond parent's end (PR 64158)):
  531. if (m_bFirstDurationHasBeenSet  &&
  532. m_ulFirstDuration < ulActualDurBeyondSyncBase)
  533. {
  534.     bSetChildCurEndClippedByParent = TRUE;
  535.     if (m_ulFirstDuration > ulChildDelayBeyondStartOfThis)
  536.     {
  537. m_pParser->resetTimelineElementDuration(pElementID,
  538. m_ulFirstDuration -
  539. // /Fixes PR 64160 (ensync="first" version):
  540. ulChildDelayBeyondStartOfThis,
  541. // /Changed to *child* prior dur while fixing PR 66391:
  542. ulActualDurBeyondSyncBase -
  543. ulChildDelayBeyondStartOfThis);
  544. // /Update dur to be used:
  545. ulRevisedActualDurBeyondSyncBase = m_ulFirstDuration -
  546. ulChildDelayBeyondStartOfThis;
  547. m_pParser->m_pTimelineElementManager->notify(pElementID);
  548.     }
  549.     else // /Begin offset is beyond parent's end, so remove it:
  550.     // /Fixes PR 64158 (endsync="first" version)
  551.     {
  552. bSetCompletelyRemovedFromTimeline = TRUE;
  553. HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  554. handleTrackRemoval((const char*)pElementID,
  555. (INT32)m_pSourceElement->m_pNode->m_nGroup);
  556.     }
  557. }
  558.     }
  559.     if (!(*m_pChildDurAddedMap)[pElementID])
  560.     {
  561. m_nDurationAdded++;
  562. (*m_pChildDurAddedMap)[pElementID] = (void*)ulRevisedActualDurBeyondSyncBase;
  563.     }
  564.     ULONG32 ulChildrenCount = m_pChildren->GetCount();
  565.     // /Fixes PR 56481 find children of this par that don't have a scheduled
  566.     // begin, i.e., are awaiting an event to begin.  endsync="last" says to
  567.     // ignore any children that never play, and we don't know if those
  568.     // event-based begin children will play or not so ignore them for now,
  569.     // and if they ever do begin, *then* re-compute this par's duration:
  570.     ULONG32 ulNonEventBasedBeginChildCount = 0;
  571.     CSmilElement* pCurChildElem = NULL;
  572.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  573.     for(i; i != m_pChildren->End(); ++i)
  574.     {
  575. CSmilTimelineElement* pTmlnElement =
  576. (CSmilTimelineElement*)(*i);
  577. if (pTmlnElement  &&  pTmlnElement->m_pSourceElement)
  578. {
  579.     BOOL isCurAddDurElem = FALSE;
  580.     if (!strcmp(pTmlnElement->m_pSourceElement->m_pNode->m_id,
  581.     pElementID))
  582.     {
  583. isCurAddDurElem = TRUE;
  584. pCurChildElem = pTmlnElement->m_pSourceElement;
  585. if (bSetChildCurEndClippedByParent  &&  pCurChildElem)
  586. {
  587.     pCurChildElem->m_bCurEndClippedByParent = TRUE;
  588. }
  589. if (bSetCompletelyRemovedFromTimeline  &&  pCurChildElem)
  590. {
  591.     pCurChildElem->m_bInsertedIntoTimeline = FALSE;
  592. }
  593.     }
  594.     if ((pTmlnElement->m_pSourceElement->
  595.     m_bHasAtLeastOneNonEventBasedBegin  ||
  596.     // /Do this so this par can re-resolve its duration if &
  597.     // when an event-based-begin child gets added (and thus
  598.     // technically now is a child with a clock-valued begin):
  599.     isCurAddDurElem) )
  600.     {
  601. ulNonEventBasedBeginChildCount++;
  602.     }
  603. }
  604.     }
  605.     
  606.     if (!bHandled  &&
  607.     (m_nDurationAdded >= ulNonEventBasedBeginChildCount  &&
  608.     // /If endsync is all, we need to wait for *all* to be added:
  609.     (SMILEventSourceAll!=m_pSourceElement->m_nEndsyncEventSourceTag  ||
  610.     m_nDurationAdded == ulChildrenCount) )  &&
  611.     !m_bDurationEvent)
  612.     {
  613. BOOL bUpdateDurMightBeNeeded = FALSE;
  614. // /Helps fix PR 62688(par): if duration was set before, but only to
  615. // hold the timeline open until all (or a particular) child duration
  616. // became known, then we want to ignore the durationSet flag so that
  617. // we call duartionResolved() instead of adjustDuration();
  618. BOOL bIgnoreDurationSetFlag = bIsCurChildsFirstAddDuration  &&
  619. (WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDelay +
  620. m_pSourceElement->m_ulDuration);
  621. // /First, if duration has already been set, then pElement must be an
  622. // event-based-begin child that just resolved, so we need to reset
  623. // our duration appropriately:
  624. if (m_bDurationSet  &&  pCurChildElem  &&  !bIgnoreDurationSetFlag  &&
  625. !pCurChildElem->m_bHasAtLeastOneNonEventBasedBegin)
  626. {
  627.     bUpdateDurMightBeNeeded = TRUE;  // /(PR 59851 hits this line.)
  628. }
  629.         // Switch on different endsync values
  630. if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  631.     SMILEventSourceFirst)
  632. {
  633.     if (bUpdateDurMightBeNeeded)
  634.     {
  635. if (ulActualDurBeyondSyncBase == m_ulFirstDuration)
  636. {
  637.     // /XXXEH- revisit now that addDuration accts for endsync:
  638.     ULONG32 ulOldDur = m_pSourceElement->m_ulDuration;
  639.     adjustDuration();
  640.     HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulFirstDuration);
  641.     // /Other half of fix for PR 50679: if updated duration
  642.     // is less than prior dur, then update timeline element:
  643.     if (ulOldDur > m_pSourceElement->m_ulDuration)
  644.     {
  645. // /Reset duration-set flag to FALSE since we want to
  646. // override (reset) the dur now that this last child
  647. // has been resolved (presumably after playback of
  648. // this par began):
  649. m_bDurationSet = FALSE;
  650. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  651. m_pSourceElement->getPureDuration());
  652. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  653.     }
  654. }
  655.     }
  656.     else
  657.     {
  658. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  659. m_pSourceElement->getPureDuration());
  660. durationResolved(m_ulFirstDuration, TRUE);
  661.     }
  662. }
  663. else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  664.     SMILEventSourceLast)
  665. {
  666.     if (bUpdateDurMightBeNeeded)
  667.     {
  668. if (ulActualDurBeyondSyncBase == m_ulLastDuration)
  669. {
  670.     adjustDuration();
  671. }
  672.     }
  673.     else
  674.     {
  675. // /Helps fix PR 62688(par version when endsync="last" is
  676. // explicitly declared): if we previously resolved our
  677. // duration to "unresolved" to hold timeline open, then we
  678. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  679. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  680. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  681. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  682. {
  683.     // /Fixes part 3 of PR 79699 (explicit endsync=last version)
  684.     // where it plays as indefinite because outer par wasn't
  685.     // adjusting for new non-indef dur:
  686.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  687.     bIsCurChildsFirstAddDuration)
  688.     {
  689. HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
  690. // /Trick adjustDuration() into doing its thing
  691. // since this is last child being added for 1st time:
  692. m_bDurationSet = TRUE;
  693.     }
  694.     adjustDuration();
  695.     m_bDurationSet = FALSE;
  696. }
  697. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  698. m_pSourceElement->getPureDuration());
  699. // /To fix PR 59584(par w/event-ended child), w/"last"), use
  700. // m_pSourceE.'s dur, not m_ulLastDuration since latter may
  701. // be wrong if some elements stopped early
  702. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  703.     }
  704. }
  705. else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  706.     SMILEventSourceAll)
  707. {
  708.     if (bUpdateDurMightBeNeeded)
  709.     {
  710. if (ulActualDurBeyondSyncBase == m_ulLastDuration)
  711. {
  712.     // /adjustDuration() assumes endsync=last which is OK
  713.     // since we've got all durations:
  714.     adjustDuration();
  715. }
  716.     }
  717.     else
  718.     {
  719. // /Helps fix PR 59584(simplified): if we previously resolved
  720. // our duration to "unresolved" to hold timeline open, then we
  721. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  722. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  723. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  724. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  725. {
  726.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  727.     bIsCurChildsFirstAddDuration)
  728.     {
  729. HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
  730. // /See "part 2 of PR 79699" below; don't want to mess
  731. // with this unless there's content that asserts here:
  732. HX_ASSERT(m_bDurationSet);
  733.     }
  734.     adjustDuration();
  735. }
  736. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  737. m_pSourceElement->getPureDuration());
  738. // /Reset duration-set flag to FALSE since we want to
  739. // override (reset) the dur now that this last child has been
  740. // resolved (presumably after playback of this par began):
  741. m_bDurationSet = FALSE;
  742. // /To fix PR 59584(par w/event-ended child), w/"all"), use
  743. // m_pSourceE.'s dur, not m_ulLastDuration since latter may
  744. // be wrong if some elements stopped early
  745. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  746.     }
  747. }
  748. else
  749. {
  750.     if (bUpdateDurMightBeNeeded)
  751.     {
  752. if (ulActualDurBeyondSyncBase == m_pSourceElement->m_ulDuration)
  753. {
  754.     adjustDuration();
  755. }
  756.     }
  757.     else
  758.     {
  759. // /Helps fix PR 62688(par version): if we previously resolved
  760. // our duration to "unresolved" to hold timeline open, then we
  761. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  762. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  763. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  764. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  765. {
  766.     // /Fixes part 2 of PR 79699 (imlicit endsync=last version)
  767.     // where it plays as indefinite because outer par wasn't
  768.     // adjusting for new non-indef dur:
  769.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  770.     bIsCurChildsFirstAddDuration)
  771.     {
  772. HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
  773. // /Trick adjustDuration() into doing its thing
  774. // since this is last child being added for 1st time:
  775. m_bDurationSet = TRUE;
  776.     }
  777.     adjustDuration();
  778.     m_bDurationSet = FALSE;
  779. }
  780. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  781. m_pSourceElement->getPureDuration());
  782. durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  783.     }
  784. }
  785. // /This if() block fixes PR 56686 (version 3) and
  786. // PR 61174 (version 3): if time container has longer dur than its
  787. // children and it is not a time-child of the <body>, then its dur
  788. // was never getting accounted for, but now the outer time container
  789. // sets the duration if its dur is longer than its group's so far;
  790. // outer time contnr can only be a par if body has multiple children:
  791. if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  792. {
  793.     // /XXXEH- handle <body><switch><par> and <body><a><par>
  794.     if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  795.     m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  796.     m_pSourceElement->m_pNode->
  797.     m_pParent->m_bIsOuterWrapperTimeContainer) )
  798.     {
  799. UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
  800. // /The group duration should be the duration of this
  801. // outer-most time container:
  802. HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  803. resolveGroupDurToOuterTimeContainerDur(
  804. ulGroup, m_pSourceElement->m_ulDuration);
  805.     }
  806. }
  807.     }
  808. }
  809. void
  810. CSmilTimelinePar::elementResolved(CSmilTimelineElement* pEventElement)
  811. {
  812.     parExclElementResolved(pEventElement);
  813. }
  814. void
  815. CSmilTimelinePar::durationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
  816. {
  817.     parExclDurationResolved(ulDuration, bUpdateChildren);
  818. }
  819. #if 0
  820. #error: **HEY: if this code ever gets enabled, handle CSmilTimelineExcl as well:
  821. void 
  822. CSmilTimelinePar::setEndsync(EndsyncType eType, 
  823.      const char* pEndsyncID,
  824.      UINT32 ulEndsyncClockValue)
  825. {
  826.     m_eEndsyncType = eType;
  827.     m_ulEndsyncClockValue = ulEndsyncClockValue;
  828.     if(pEndsyncID)
  829.     {
  830. m_pEndsyncID = new char[strlen(pEndsyncID)+1];
  831. strcpy(m_pEndsyncID, pEndsyncID); /* Flawfinder: ignore */
  832.     }
  833. }
  834. #endif
  835. /***************************************************************************/
  836. /*
  837.  * CSmilTimelineSeq methods
  838.  */
  839. CSmilTimelineSeq::CSmilTimelineSeq(CSmilElement* pSourceElement,
  840.    CSmilParser* pParser):
  841.     CSmilTimelineElement(pSourceElement, pParser),
  842.     m_nDurationAdded(0)
  843. {
  844. }
  845. void 
  846. CSmilTimelineSeq::addDuration(UINT32 ulDuration, 
  847.       UINT32 ulDelay,
  848.       UINT32 ulChildDelayBeyondStartOfItsSyncBase, 
  849.       const char* pID)
  850. {
  851.     HX_ASSERT(m_pChildren);
  852. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  853.     {
  854. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  855. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  856. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  857. ::fprintf(f1, "CSmilTimelineSeq{%s}::addDuration(dur=%lu, delay=%lu, "
  858. "childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sEn",
  859. (const char*)m_pID, ulDuration, ulDelay,
  860. ulChildDelayBeyondStartOfItsSyncBase, pID,
  861. m_bDurationSet?"TRU":"FALS");
  862. ::fclose(f1);
  863. bFirstTimeAddDurDebugout = FALSE;
  864.     }
  865. #endif
  866.     // /I don't think we want to/need to use ulChildDelay; it is > 0 in
  867.     // "BUG-20010502_repeatedElementWithBeginOf3sAndEndOf15s.smil" but
  868.     // that works (offset-wise) so no need to use ulChildDelay...:
  869.     ULONG32 ulActualDurBeyondSyncBase = ulDuration;
  870.     // /Fixes case where this seq has a begin offset from its parent and
  871.     // doesn't have an explicit end or dur; the child being added here
  872.     // ended up playing too short by the amount of this's begin offset:
  873.     BOOL bDurationIncludesDelayBeyondSyncbase = FALSE;
  874.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  875.     {
  876. ulActualDurBeyondSyncBase +=
  877. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  878. bDurationIncludesDelayBeyondSyncbase = TRUE;
  879.     }
  880.     if (ulChildDelayBeyondStartOfItsSyncBase > 0)
  881.     {
  882. // /Helps fix PR 6XXXX: be sure to account for child's delay beyond
  883. // its prior sibling in this seq, or the seq itself if no prior sib:
  884. ulActualDurBeyondSyncBase -= ulChildDelayBeyondStartOfItsSyncBase;
  885.     }
  886.     else
  887.     {
  888. HX_ASSERT(0 == ulChildDelayBeyondStartOfItsSyncBase  &&
  889. "ehodge: negative delay in seq!?");
  890.     }
  891.     BOOL bIsCurChildsFirstAddDuration = FALSE;
  892.     ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
  893.     if (!(*m_pChildDurAddedMap)[pID])
  894.     {
  895. bIsCurChildsFirstAddDuration = TRUE;
  896.     }
  897.     else
  898.     {
  899. ulCurChildPriorAddedDuration =
  900. (ULONG32)((*m_pChildDurAddedMap)[pID]);
  901.     }
  902.     if(!m_bDurationSet)
  903.     {
  904. if(m_pSourceElement->m_ulDuration == (UINT32)-1)
  905. {
  906.     m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
  907.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  908.     bDurationIncludesDelayBeyondSyncbase;
  909. }
  910. // /Helps fix PR 62688 and PR 59584: never go higher duration than
  911. // WAY_IN_THE_FUTURE so overall timeline doesn't further extend:
  912. else if (WAY_IN_THE_FUTURE == ulActualDurBeyondSyncBase  ||
  913. WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration)
  914. {
  915.     m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
  916.     if (m_pSourceElement->m_ulDelay > 0)
  917.     {
  918. if (m_pSourceElement->m_ulDuration >=
  919. m_pSourceElement->m_ulDelay)
  920. {
  921.     m_pSourceElement->m_ulDuration -=
  922.     m_pSourceElement->m_ulDelay;
  923. }
  924. else
  925. {
  926.     m_pSourceElement->m_ulDuration = 0;
  927. }
  928.     }
  929.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  930.     bDurationIncludesDelayBeyondSyncbase;
  931. }
  932. else
  933. {
  934.     m_pSourceElement->m_ulDuration += ulActualDurBeyondSyncBase;
  935.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  936.     bDurationIncludesDelayBeyondSyncbase;
  937. }
  938.     }
  939.     // /Fixes unfiled(?) bug found when PR 52110 was fixed: seq with begin
  940.     // offset>0 and explicit dur was not accounting for this offset in its
  941.     // duration, but parent's addDuration() counts on that being done:
  942.     else if (m_pSourceElement->m_bHasExplicitDur  &&
  943.     !m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  944.     {
  945. if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  946. {
  947.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  948.     bDurationIncludesDelayBeyondSyncbase;
  949.     m_pSourceElement->m_ulDuration +=
  950.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  951. }
  952.     }
  953.     if (!(*m_pChildDurAddedMap)[pID])
  954.     {
  955. m_nDurationAdded++;
  956. (*m_pChildDurAddedMap)[pID] = (void*)ulActualDurBeyondSyncBase;
  957.     }
  958.     if(m_nDurationAdded == m_pChildren->GetCount()  ||
  959.     // /Helps fix PR 59584: if our dur is unresolved, then we need to
  960.     // notify our parent (and on up the chain) that there is an
  961.     // currently-indefinite-duration element in the presentation:
  962.     WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDuration +
  963.     m_pSourceElement->m_ulDelay)
  964.     {
  965. m_bDurationSet = TRUE;
  966. if (m_nDurationAdded == m_pChildren->GetCount())
  967. {
  968.     // /We need to adjust our duration in case it was temporarily set
  969.     // to indefinite; now that we have all children accounted for, we
  970.     // can correctly calculate it:  (fixes PR 59584 overall duration)
  971.     adjustDuration();
  972. }
  973.         // Add our duration to our parent
  974. if(m_pParent)
  975. {
  976.     ULONG32 ulDelayFromSyncBaseBegin = 0;
  977.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  978.     {
  979. ulDelayFromSyncBaseBegin =
  980. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  981. // /Fixes PR 68875: be sure to add offset from syncbase if
  982. // not already included:
  983. if ((UINT32)-1 != ulDelayFromSyncBaseBegin
  984. &&  ulDelayFromSyncBaseBegin > 0  &&
  985. !m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  986. {
  987.     m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
  988.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
  989. }
  990.     }
  991.     m_pParent->addDuration( 
  992.     m_pSourceElement->m_ulDuration, 
  993.     m_pSourceElement->m_ulDelay,
  994.     ulDelayFromSyncBaseBegin, m_pID);
  995.     m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
  996. }
  997. // /This if() block fixes PR 56686 (version 2) and
  998. // PR 61174 (version 2): if time container has longer dur than its
  999. // children and it is not a time-child of the <body>, then its dur
  1000. // was never getting accounted for, but now the outer time container
  1001. // sets the duration if its dur is longer than its group's so far:
  1002. if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  1003. {
  1004.     if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  1005.     m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  1006.     m_pSourceElement->m_pNode->
  1007.     m_pParent->m_bIsOuterWrapperTimeContainer) )
  1008.     {
  1009. BOOL bDoResolveGroupDur = TRUE;
  1010. UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
  1011. if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
  1012. {
  1013.     ulGroup = 0;
  1014.     // /If we're outer seq wrapper around multiple groups
  1015.     // (or "clips"), then let each group outer time container
  1016.     // resolve its group duration:
  1017.     if (m_pChildren->GetCount() > 1)
  1018.     {
  1019. bDoResolveGroupDur = FALSE;
  1020.     }
  1021. }
  1022. if (bDoResolveGroupDur)
  1023. {
  1024.     // /The group duration should be the duration of this
  1025.     // outer-most time container:
  1026.     HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  1027.     resolveGroupDurToOuterTimeContainerDur(
  1028.     ulGroup, m_pSourceElement->m_ulDuration);
  1029. }
  1030.     }
  1031. }
  1032.         // Now we know the duration of this <seq>, so 
  1033.         // we need to check the fill behavior of all our
  1034.         // children
  1035.         checkChildrenFillBehavior();
  1036. if(m_pDependent)
  1037. {
  1038.     HX_ASSERT(m_bDurationSet);
  1039.     adjustDependentDuration(m_pDependent);
  1040. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1041.     ULONG32 ulTotalDelay = 0;
  1042.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1043.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1044.     {
  1045. HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1046.     }
  1047.     if (HXR_OK !=
  1048.     m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1049.     {
  1050. goto doneSettingDependent;
  1051.     }
  1052. #else
  1053.     ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1054.     m_pSourceElement->m_ulDuration;
  1055.     // /Helps fix PR 6XXXX(seq version): if delay is already packed
  1056.     // into the duration, then don't count it twice (as can happen in
  1057.     // <seq><seq begin="1s">...</seq><seq begin="1s" ...):
  1058.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1059.     {
  1060. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1061. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  1062. {
  1063.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1064.     ulTotalDelay);
  1065.     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1066.     ulTotalDelay)
  1067.     {
  1068. ulTotalDelay -=
  1069. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1070.     }
  1071. }
  1072.     }
  1073. #endif
  1074.     if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1075.     {
  1076. HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1077. ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1078.     }
  1079.     // /XXXEH- TODO: figure out if we need to claim this is being set
  1080.     // by "parent" (which is really time base) so clip-begin-like
  1081.     // action can occur; I don't think so, however:
  1082.     m_pDependent->setDelay(ulTotalDelay, FALSE);     
  1083. }
  1084. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1085. doneSettingDependent:
  1086. #endif
  1087. // /[SMIL 1.0 Compliance] Fixes PR 23779:
  1088. // if a source has event-based timing based on this seq's
  1089. // duration, then we need to notify that source that we've
  1090. // resolved this value:
  1091. m_pParser->m_pTimelineElementManager->notify(m_pID);
  1092.     }
  1093. }
  1094. void 
  1095. CSmilTimelineSeq::setDelay(UINT32 ulDelay,
  1096.    // /NOTE: we ignore this in time containers that aren't media:
  1097.    BOOL bSetByParent)
  1098. {
  1099. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  1100.     {
  1101. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  1102. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  1103. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  1104. ::fprintf(f1, "CSmilTimelineSeq{%s}::setDelay(delay=%lu, "
  1105. "bSetByParent=%sE) m_bDelaySet=%sEn",
  1106. (const char*)m_pID, ulDelay,
  1107. bSetByParent?"TRU":"FALS",
  1108. m_bDelaySet?"TRU":"FALS");
  1109. ::fclose(f1);
  1110. bFirstTimeAddDurDebugout = FALSE;
  1111.     }
  1112. #endif
  1113.     if(m_pSourceElement->m_bBeginOffsetSet)
  1114.     {
  1115. m_pSourceElement->m_ulDelay = (
  1116. ((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
  1117. (UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
  1118.     }
  1119.     else
  1120.     {
  1121. m_pSourceElement->m_ulDelay = ulDelay;
  1122.     }
  1123.     //XXXJHUG - we need to prevent overwriting the delay when
  1124.     // setInitalDelay is called on THIS element, changing this
  1125.     // bool causes initialDelaySet to return TRUE.
  1126.     m_bDelaySet = TRUE;
  1127.     if(m_pChildren && m_pChildren->GetCount() > 0)
  1128.     {
  1129. // set delay on first child of seq
  1130. CSmilTimelineElement* pElement = 
  1131.     (CSmilTimelineElement*)m_pChildren->GetHead();
  1132. pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  1133. // /To fix it so second group plays (PR6XXX5) after fix for (PR6XXX4),
  1134. // need to set the delay of all children since each is not dependent
  1135. // on the prior; problem is that a child 'n' with an explicit dur will
  1136. // (now) tell its parent its dur during the above setDelay() call and
  1137. // that will end up with this->setDuration() call happening too early,
  1138. // farther below, resulting in all groups > n getting a 0 duration:
  1139. SMILNode* pSyncAncestor = m_pParser? m_pParser->getSyncAncestor(
  1140. m_pSourceElement->m_pNode) : NULL;
  1141. if (!pSyncAncestor  ||  (SMILBody == pSyncAncestor->m_tag  &&
  1142. m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer) )
  1143. {
  1144.     // /Need to set the delays of all children to 0 since each starts its
  1145.     // own "clip" (group):
  1146.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  1147.     ++i;  // /Already done for group 0, above.
  1148.     for(; i != m_pChildren->End(); ++i)
  1149.     {
  1150. pElement = (CSmilTimelineElement*)(*i);
  1151. // /If 0 != this's delay, then body must have begin="x" on it
  1152. // and subsequent groups should not include that delay:
  1153. HX_ASSERT(0 == m_pSourceElement->m_ulDelay);
  1154. pElement->setDelay(0, TRUE);
  1155.     }
  1156. }
  1157.     }
  1158.     // /Fixes PR 24046 (SMIL 2+ seq version): if there are no children,
  1159.     // then the seq's duration is zero, so set it to 0:
  1160.     else if (m_pSourceElement->m_ulDuration == (UINT32)-1)
  1161.     {
  1162. m_pSourceElement->m_ulDuration = 0;
  1163.     }
  1164.     if (m_pSourceElement->m_ulDuration != (UINT32)-1)
  1165.     {
  1166. setDuration(m_pSourceElement->m_ulDuration);
  1167. #if 0 /* 20011024 */
  1168. // /Fixes seq version of PR 61174(version1) and PR 56686
  1169. // (version1): we know our duration already, so let's declare it
  1170. // resolved so we get added to our parent (in case none of our
  1171. // XXXNH: for some reason, despite being if-zeroed-out, this causes a compiler
  1172. // error on linux!
  1173. //#error: DUDE!?!: children of seq can't have unresolved begins!:
  1174.         // children have scheduled begin times in which case our
  1175. // ::addDuration() would not get called up front and the overall
  1176. // presentation would not include our duration at first):
  1177. if (m_pSourceElement->m_bHasExplicitDur  ||
  1178. m_pSourceElement->m_bHasExplicitEnd)
  1179. {
  1180.     // /Be sure not to override a shorter duration that may have
  1181.     // been imposed on us by our parent:
  1182.     if (!m_bDurationSet  ||
  1183.     !m_pSourceElement->m_bAddDurationAlreadyDone)
  1184.     {
  1185. HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  1186. m_bDurationSet = TRUE;
  1187. if (m_pParent)
  1188. {
  1189.     ULONG32 ulDelayFromSyncBaseBegin = 0;
  1190.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  1191.     {
  1192. ulDelayFromSyncBaseBegin =
  1193. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1194. if (ulDelayFromSyncBaseBegin > 0  &&
  1195. !m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1196. {
  1197.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  1198.     TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
  1199.     m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
  1200. }
  1201.     }
  1202.     m_pParent->addDuration(m_pSourceElement->m_ulDuration,
  1203.     m_pSourceElement->m_ulDelay,
  1204.     ulDelayFromSyncBaseBegin, m_pID);
  1205.     m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
  1206. }
  1207.     }
  1208.     HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
  1209. }
  1210. #endif
  1211.     }
  1212.     //[SMIL 1.0 Compliance] Helps fix PR 14420 and 23025:
  1213.     // if a source has event-based timing based on this seq's
  1214.     // begin time (delay) then we need to notify that source
  1215.     // that we've resolved this value:
  1216.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1217. }
  1218. void
  1219. CSmilTimelineSeq::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
  1220.   BOOL bDurationExtendingDueToPause)
  1221. {
  1222.     ASSERT(m_pChildren  ||  0==ulDuration);
  1223.     if (bDurationExtendingDueToPause)
  1224.     {
  1225. // /Need to handle this case:
  1226. HX_ASSERT(!bDurationExtendingDueToPause);
  1227.     }
  1228.     if(!m_bDurationSet  ||
  1229.     // /Adding this fixes PR 27644 and other cases where explicit
  1230.     // dur|end of parent was being ignored by explicit (and larger)
  1231.     // dur|end of child seq.  This allows repeatDur to work when
  1232.     // parent has explicit dur|end since repeatDur creates a seq
  1233.     // with an explicit dur:
  1234.     bSetFromParent)
  1235.     {
  1236. m_pSourceElement->m_ulDuration = ulDuration;
  1237. m_bDurationSet = TRUE;
  1238.     }
  1239.     UINT32 ulDurationLeft = m_pSourceElement->m_ulDuration;
  1240.     RepeatTag repeatTag = RepeatUnknown;
  1241.     if (m_pChildren) // /Fixes crash in case of a "<seq></seq>" (PR 65069).
  1242.     { 
  1243. CHXSimpleList::Iterator i = m_pChildren->Begin(); 
  1244. for(; i != m_pChildren->End(); ++i) 
  1245.     CSmilTimelineElement* pTmLnElement = (CSmilTimelineElement*)(*i); 
  1246.     CSmilElement* pElement = pTmLnElement->m_pSourceElement;
  1247.     if (!setElementDuration(ulDurationLeft, pTmLnElement))
  1248.     {
  1249. break;
  1250.     }
  1251.     // /Fixes PR 99498: make sure m_pSourceElement's time values are
  1252.     // in same time-coords as pElement's before comparing the two;
  1253.     // in this bug, a seq that began at 15s (15000 delay) had a
  1254.     // duration that did not include that delay so the below PR 66391
  1255.     // fix's if() was erroneously evaluating to true, thus ending
  1256.     // this's children early.  Use this's soureElement's dur+delay,
  1257.     // not its m_ulDuration (which may or may not include delay):
  1258.     UINT32 ulDurationPlusDelayOfThisSeq =
  1259.     m_pSourceElement->getPureDuration() +
  1260.     m_pSourceElement->m_ulDelay;
  1261.     // /Helps fix PR 66391: if this's m_ulDuration has shortened and
  1262.     // its child(ren)'s duration is shortened to zero as a result,
  1263.     // then remove child track if it begins too late to ever play:
  1264.     if (pElement  &&  pElement->m_pHandler  &&
  1265.     pElement->m_ulDelay > ulDurationPlusDelayOfThisSeq  &&
  1266.     pElement->m_bInsertedIntoTimeline)
  1267.     {
  1268. pElement->m_bCurEndClippedByParent = TRUE;
  1269. HX_ASSERT(0 == ulDurationLeft);
  1270. BOOL bCurElementIsTimeContainer =
  1271. m_pParser->isTimeContainerObject(pElement->m_pNode);
  1272. HX_ASSERT(!bCurElementIsTimeContainer  &&  "ehodge:handle_removing_grandkids");
  1273. HX_RESULT retvl = pElement->m_pHandler->handleTrackRemoval(
  1274. (const char*)pElement->m_pNode->m_id,
  1275. (INT32)pElement->m_pNode->m_nGroup);
  1276. if (HXR_OK == retvl)
  1277. {
  1278.     // /Notify syncArc dependents that it ended early:
  1279.     m_pParser->m_pTimelineElementManager->notify((const char*)pElement->m_pNode->m_id);
  1280. }
  1281.     }
  1282.     } 
  1283.     if(m_pDependent)
  1284.     {
  1285. HX_ASSERT(m_bDurationSet);
  1286. adjustDependentDuration(m_pDependent);
  1287. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1288. ULONG32 ulTotalDelay = 0;
  1289.         if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1290. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1291. {
  1292.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1293. }
  1294. if (HXR_OK !=
  1295. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1296. {
  1297.     goto doneSettingDependent;
  1298. }
  1299. #else
  1300. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1301. m_pSourceElement->m_ulDuration;
  1302. // /Helps fix PR 6XXXX(seq version): if delay is already packed
  1303. // into the duration, then don't count it twice (as can happen in
  1304. // <seq><seq begin="1s">...</seq><seq begin="1s" ...):
  1305. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1306. {
  1307.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1308. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  1309.     {
  1310. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1311. ulTotalDelay);
  1312. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1313. ulTotalDelay)
  1314. {
  1315.     ulTotalDelay -=
  1316.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1317. }
  1318.     }
  1319. }
  1320. #endif
  1321. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1322. {
  1323.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1324.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1325. }
  1326. // /XXXEH- TODO: figure out if we need to claim this is being set
  1327. // by "parent" (which is really time base) so clip-begin-like
  1328. // action can occur; I don't think so, however:
  1329. m_pDependent->setDelay(ulTotalDelay, FALSE);
  1330.     }
  1331. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1332. doneSettingDependent:
  1333. #endif
  1334.     //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025:
  1335.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1336. }
  1337. void
  1338. CSmilTimelineSeq::setMaxDuration(UINT32 ulMaxDuration)
  1339. {
  1340.     HX_ASSERT(m_pChildren);
  1341.     m_bMaxDurationSet = TRUE;
  1342.     m_pSourceElement->m_ulMaxDuration = ulMaxDuration;
  1343.     if (m_pChildren  &&  m_bDelaySet)
  1344.     {
  1345. HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  1346. CSmilTimelineElement* pElement = (CSmilTimelineElement*)m_pChildren->GetHead();
  1347. pElement->setMaxDuration(ulMaxDuration);
  1348.     }
  1349. }
  1350. void 
  1351. CSmilTimelineSeq::adjustDependentDuration(CSmilTimelineElement* pDependent)
  1352. {
  1353.     if(m_bDurationSet || m_bMaxDurationSet)
  1354.     {
  1355. UINT32     ulDurationLeft = m_bDurationSet?m_pSourceElement->m_ulDuration:
  1356.     m_pSourceElement->m_ulMaxDuration;
  1357. UINT32 ulOriginalDurationLeft = ulDurationLeft;
  1358. if (m_pSourceElement->m_ulMinActiveDur>ulDurationLeft)
  1359. {
  1360.     ulDurationLeft = m_pSourceElement->m_ulMinActiveDur;
  1361. }
  1362. BOOL     bAdjusted = FALSE;
  1363. RepeatTag   repeatTag = RepeatUnknown;
  1364. if (m_pChildren) // /Fixes crash in case of a "<seq></seq>" (PR 65069).
  1365.     CHXSimpleList::Iterator i = m_pChildren->Begin(); 
  1366.     for(; i != m_pChildren->End(); ++i) 
  1367.     { 
  1368. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i); 
  1369. UINT32 ulChildDuration = pElement->getDuration(); 
  1370.  
  1371. if (pElement == pDependent) 
  1372.     bAdjusted = TRUE; 
  1373.  
  1374. if (bAdjusted) 
  1375.     if (pElement->getDelay() != (UINT32)-1)
  1376.     {
  1377. HX_ASSERT(pElement->getDelay() < WAY_IN_THE_FUTURE  &&
  1378.     "need to reset delay b4 dur!");
  1379.     }
  1380.     // /Fixes PR 59584(parFollowsPar version):  If seq has
  1381.     // unresolved-dur child, don't set dur of next sibling
  1382.     // if it doesn't have delay set yet:
  1383.     else if (0 == ulDurationLeft  &&  WAY_IN_THE_FUTURE ==
  1384.     ulOriginalDurationLeft)
  1385.     {
  1386. break; // /Don't do anything.
  1387.     }
  1388.     // /Helps fix full repro case of PR 59584: second par
  1389.     // in seq will have delay>0 and interim duration
  1390.     // of WAY_IN_THE_FUTURE *minus* delay:
  1391.     if (WAY_IN_THE_FUTURE <= ulOriginalDurationLeft)
  1392.     {
  1393. ulDurationLeft = WAY_IN_THE_FUTURE;
  1394. setElementDuration(ulDurationLeft, pElement);
  1395. break; // /Go no further for now.
  1396.     }
  1397.     if (!setElementDuration(ulDurationLeft, pElement)) 
  1398.     { 
  1399. break; 
  1400.     } 
  1401. else 
  1402.     if(ulDurationLeft >= ulChildDuration) 
  1403.     { 
  1404. ulDurationLeft -= ulChildDuration; 
  1405.     } 
  1406.     else 
  1407.     { 
  1408. ulDurationLeft = 0; 
  1409.     } 
  1410.     } 
  1411. if (!bAdjusted && m_pParent)
  1412. {
  1413.     m_pParent->adjustDependentDuration(pDependent);
  1414. }
  1415.     }
  1416. }
  1417. void 
  1418. CSmilTimelineSeq::resetDelay(UINT32 ulDelay)
  1419. {
  1420.     INT32 lAdjustedDelay = 0;
  1421.     UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;
  1422.     if(m_pSourceElement->m_bBeginOffsetSet)
  1423.     {
  1424. lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
  1425. m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
  1426.     }
  1427.     else
  1428.     {
  1429. m_pSourceElement->m_ulDelay = ulDelay;
  1430.     }
  1431.     if(m_pChildren && m_pChildren->GetCount() > 0)
  1432.     {
  1433. // set delay on first child of seq
  1434. CSmilTimelineElement* pElement = 
  1435.     (CSmilTimelineElement*)m_pChildren->GetHead();
  1436. #if 200110241
  1437. if (m_pSourceElement->m_ulDelay !=
  1438. pElement->m_pSourceElement->m_ulDelay)
  1439. {
  1440.     pElement->resetDelay(m_pSourceElement->m_ulDelay);
  1441. }
  1442. #else
  1443. pElement->resetDelay(m_pSourceElement->m_ulDelay);
  1444. #endif
  1445.     }
  1446.     // /To fix PR 59851(seq of seqs), we need to update our next-in-seq
  1447.     // (m_pDependent) as well as make sure sync-arc listeners know we've
  1448.     // changed our overall time bounds delay as well;
  1449.     if (m_pDependent && m_bDurationSet  &&
  1450.     ulPriorDelay != m_pSourceElement->m_ulDelay)
  1451.     {
  1452. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1453. ULONG32 ulTotalDelay = 0;
  1454.         if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1455. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1456. {
  1457.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1458. }
  1459. if (HXR_OK !=
  1460. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1461. {
  1462.     goto doneSettingDependent;
  1463. }
  1464. #else
  1465. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1466. m_pSourceElement->m_ulDuration;
  1467. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1468. {
  1469.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1470. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  1471.     {
  1472. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1473. ulTotalDelay);
  1474. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1475. ulTotalDelay)
  1476. {
  1477.     ulTotalDelay -=
  1478.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1479. }
  1480.     }
  1481. }
  1482. #endif
  1483. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1484. {
  1485.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1486.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1487. }
  1488.  
  1489. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  1490.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  1491.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  1492.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  1493.     ::fprintf(f1, "nt%s:CSmilTimelineSeq::resetDelay(%lu):from %lu to %lu;"
  1494.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  1495.     ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
  1496.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  1497.     ::fclose(f1); 
  1498.     bFirstTimeAddDurDebugout = FALSE; 
  1499. #endif 
  1500.  
  1501. m_pDependent->resetDelay(ulTotalDelay);
  1502. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1503. doneSettingDependent:
  1504. #endif
  1505. // /(Added while fixing PR 59851) Let others know our begin time changed:
  1506. m_pParser->m_pTimelineElementManager->notify(m_pID);
  1507.     }
  1508. }
  1509. void 
  1510. CSmilTimelineSeq::adjustDuration()
  1511. {
  1512.     UINT32  ulDuration = 0;
  1513.     // /Fixes seq version of PR 50676 (Added during fix for PR 59584):
  1514.     ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  1515.     if (m_pChildren)
  1516.     {
  1517. CHXSimpleList::Iterator i = m_pChildren->Begin();
  1518. for(; i != m_pChildren->End(); ++i)
  1519. {
  1520.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  1521.     if ((UINT32)-1 == pElement->m_pSourceElement->m_ulDuration)
  1522.     {
  1523. // /Helps fix PR 59584 (parFollowsPar version): if child dur
  1524. // is not resolved yet, then we're unresolved:
  1525. ulDuration = WAY_IN_THE_FUTURE;
  1526. break;
  1527.     }
  1528.     ulDuration += pElement->m_pSourceElement->m_ulDuration;
  1529.     // /For PR 59584: don't go past "unresolved" dur value:
  1530.     if (ulDuration >= WAY_IN_THE_FUTURE)
  1531.     {
  1532. ulDuration = WAY_IN_THE_FUTURE;
  1533. break;
  1534.     }
  1535. }
  1536. if (!m_pSourceElement->m_bHasExplicitEnd  &&
  1537. !m_pSourceElement->m_bHasExplicitDur)
  1538. {
  1539.     // /Use child durs only if seq doesn't have explicit end or dur;
  1540.     // This helps fix PR 6XXXY:
  1541.     m_pSourceElement->m_ulDuration = ulDuration;
  1542. }
  1543. if(m_pParent)
  1544. {
  1545.     m_pParent->adjustDuration();
  1546. }
  1547. // /Fixes PR 69410: need to do this no matter what, even if prior <
  1548. // ulDur; resumed element in excl descendent should extend that excl
  1549. // but we've already told the core to limit the presentation duration,
  1550. // so extend it here as needed (also fixes part of PR 50660):
  1551. // /(Added while fixing PR 59584): if our duration got reduced, we need to
  1552. // possibly constrain the group's duration:
  1553. {
  1554.     // This group's outer time container, if this is one, needs
  1555.     // to set the duration if its dur is longer than its group's so far
  1556.     // or if its previous duration was unresolved and now is resolved:
  1557.     if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  1558.     {
  1559. if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  1560. m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  1561. m_pSourceElement->m_pNode->
  1562. m_pParent->m_bIsOuterWrapperTimeContainer) )
  1563. {
  1564.     BOOL bDoResolveGroupDur = TRUE;
  1565.     UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
  1566.     if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
  1567.     {
  1568. ulGroup = 0;
  1569. // /If we're outer wrapper around multiple groups
  1570. // (or "clips"), then let each group outer time container
  1571. // resolve its group duration:
  1572. if (m_pChildren->GetCount() > 1)
  1573. {
  1574.     bDoResolveGroupDur = FALSE;
  1575. }
  1576.     }
  1577.     if (bDoResolveGroupDur)
  1578.     {
  1579. // /The group duration should be the duration of this
  1580. // outer-most time container:
  1581. HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  1582. resolveGroupDurToOuterTimeContainerDur(
  1583. ulGroup, m_pSourceElement->m_ulDuration);
  1584.     }
  1585. }
  1586.     }
  1587. }
  1588. if(m_pDependent)
  1589. {
  1590. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1591.     ULONG32 ulTotalDelay = 0;
  1592.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1593.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1594.     {
  1595. HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1596.     }
  1597.     if (HXR_OK !=
  1598.     m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1599.     {
  1600. goto doneSettingDependent;
  1601.     }
  1602. #else
  1603.     ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1604.     m_pSourceElement->m_ulDuration;
  1605.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1606.     {
  1607. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1608. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  1609. {
  1610.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1611.     ulTotalDelay);
  1612.     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1613.     ulTotalDelay)
  1614.     {
  1615. ulTotalDelay -=
  1616. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1617.     }
  1618. }
  1619.     }
  1620. #endif
  1621.     if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1622.     {
  1623. HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1624. ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1625.     }
  1626. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  1627. {
  1628.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  1629.     ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  1630.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  1631.     ::fprintf(f1, "nt%s:CSmilTimelineSeq::adjustDuration();tresetting dependent (%s)'s delay to %lun",
  1632.     (const char*)m_pID, (const char*)m_pDependent->m_pID,
  1633.     ulTotalDelay);
  1634.     ::fclose(f1);
  1635.     bFirstTimeAddDurDebugout = FALSE;
  1636. }
  1637. #endif
  1638.     m_pDependent->resetDelay(ulTotalDelay);
  1639. }
  1640. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1641. doneSettingDependent:
  1642. ;
  1643. #endif
  1644.     }
  1645. }
  1646. BOOL
  1647. CSmilTimelineSeq::setElementDuration(UINT32& ulDurationLeft, CSmilTimelineElement* pElement)
  1648. {
  1649.     BOOL bContinue = TRUE;
  1650.     UINT32 ulChildDuration = pElement->getDuration();
  1651.     RepeatTag   repeatTag = pElement->m_pSourceElement->m_pNode->m_repeatTag;
  1652.     if (repeatTag == RepeatIndefiniteOnMe)
  1653.     {
  1654. pElement->setMaxDuration(ulDurationLeft);
  1655. ulDurationLeft = 0;
  1656. goto cleanup;
  1657.     }
  1658.     else if (repeatTag == RepeatIndefiniteOnGroup)
  1659.     {
  1660. pElement->setMaxDuration(ulDurationLeft);
  1661. bContinue = FALSE;
  1662. goto cleanup;
  1663.     }
  1664.     // no more duration left, take care of the duration of the rest of 
  1665.     // the elements
  1666.     if (0 == ulDurationLeft)
  1667.     {
  1668. pElement->setDuration(ulDurationLeft, TRUE);
  1669.     }
  1670.     // if this is the last child, then enforce the duration whatever
  1671.     // left
  1672.     else if (pElement == m_pChildren->GetTail())
  1673.     {
  1674. if (ulChildDuration == (UINT32)-1  &&
  1675. ulDurationLeft >= WAY_IN_THE_FUTURE)
  1676. {
  1677.     // /Doing this instead of setDuration() fixes PR 65741 when outer
  1678.     // seq gets held open due to tracks' durations setting in a
  1679.     // certain order.  In this case, don't override possible child
  1680.     // explicit dur or end:
  1681.     pElement->setMaxDuration(ulDurationLeft);
  1682. }
  1683. else
  1684. {
  1685.     pElement->setDuration(ulDurationLeft, TRUE);
  1686. }
  1687. bContinue = FALSE;
  1688.     }
  1689.     // unknown duration, so we apply max. duration here
  1690.     else if (ulChildDuration == (UINT32)-1)
  1691.     {
  1692. pElement->setMaxDuration(ulDurationLeft);
  1693. bContinue = FALSE;
  1694.     }
  1695.     else
  1696.     {
  1697. if(ulDurationLeft >= ulChildDuration)
  1698. {
  1699.     ulDurationLeft -= ulChildDuration;
  1700. }
  1701. else
  1702. {
  1703.     pElement->setDuration(ulDurationLeft, TRUE);
  1704.     ulDurationLeft = 0;
  1705. }
  1706.     }
  1707. cleanup:
  1708.     return bContinue;
  1709. }
  1710. /***************************************************************************/
  1711. // /XXXEH- see if any or all of the following can be combined with
  1712. // CSmilTimelinePar methods, above (with added params for dealing
  1713. // with Excl in minor places):
  1714. /*
  1715.  * CSmilTimelineExcl methods
  1716.  */
  1717. CSmilTimelineExcl::CSmilTimelineExcl(CSmilElement* pSourceElement,
  1718.    CSmilParser* pParser):
  1719.     CSmilTimelineElement(pSourceElement, pParser),
  1720.     m_nDurationAdded(0),
  1721.     m_ulFirstDuration(0),
  1722.     m_bFirstDurationHasBeenSet(FALSE),
  1723.     m_ulLastDuration(0)
  1724. {
  1725. }
  1726. CSmilTimelineExcl::~CSmilTimelineExcl()
  1727. {
  1728. }
  1729. void 
  1730. CSmilTimelineExcl::setDelay(UINT32 ulDelay,
  1731.    // /NOTE: we ignore this in time containers that aren't media:
  1732.    BOOL bSetByParent)
  1733. {
  1734. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  1735.     {
  1736. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  1737. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  1738. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  1739. ::fprintf(f1, "CSmilTimelineExcl{%s}::setDelay(delay=%lu, "
  1740. "bSetByParent=%sE) m_bDelaySet=%sEn",
  1741. (const char*)m_pID, ulDelay,
  1742. bSetByParent?"TRU":"FALS",
  1743. m_bDelaySet?"TRU":"FALS");
  1744. ::fclose(f1);
  1745. bFirstTimeAddDurDebugout = FALSE;
  1746.     }
  1747. #endif
  1748.     if(m_pSourceElement->m_bBeginOffsetSet)
  1749.     {
  1750. m_pSourceElement->m_ulDelay = (
  1751. ((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
  1752. (UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
  1753.     }
  1754.     else
  1755.     {
  1756. m_pSourceElement->m_ulDelay = ulDelay;
  1757.     }
  1758.     if (!m_bDelayEvent)
  1759.     {
  1760. m_bDelaySet = TRUE;
  1761. ULONG32 ulNumChildrenWithNonEventBasedBegins = 0;
  1762. if(m_pChildren)
  1763. {
  1764.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  1765.     for(; i != m_pChildren->End(); ++i)
  1766.     {
  1767. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  1768. // /Don't set delay of children with no valid begin time; the
  1769. // default begin of an excl child is "indefinite".  Note that
  1770. // sync-arc begins of elements that are skipped during this
  1771. // delay-setting-by-parent operation will be OK when they
  1772. // resolve because the resolved time has the delay built in:
  1773. // /Note: tested this with <a> child and it works fine,
  1774. if (pElement->m_pSourceElement  &&
  1775. (pElement->m_pSourceElement->m_bBeginOffsetSet
  1776. #if defined(XXXEH_HANDLE_MULTIPLE_EXCL_CHILD_SCHEDULED_BEGINS)
  1777.  /*can't do this fix yet because excl child w/beginOffset>0 must wait*/
  1778. // /If parent excl begins on event, child with non-
  1779. // event begin time won't yet have beginOffsetSet;
  1780. // fixes PR 56686(version 7 and 8):
  1781. || pElement->m_pSourceElement->
  1782. m_bHasAtLeastOneNonEventBasedBegin) )
  1783. #else
  1784. ) )
  1785. #endif
  1786. {
  1787.     pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  1788. }
  1789. // /else leave delay unresolved.
  1790. // /However, we need to go ahead and see which children have
  1791. // non-event-based begins (see PR 24046 fix, below, which
  1792. // this part of fix for PR 62688 broke by putting the
  1793. // following code inside the if(), above (which never got hit
  1794. // in an excl):
  1795. // /This helps fix PR 62688(excl version):
  1796. if (pElement->m_pSourceElement  &&
  1797. pElement->m_pSourceElement->
  1798. m_bHasAtLeastOneNonEventBasedBegin)
  1799. {
  1800.     ulNumChildrenWithNonEventBasedBegins++;
  1801. }
  1802.     }
  1803. }
  1804. // /Fixes PR 24046 (SMIL 2+ excl version): if there are no children,
  1805. // then the excl's duration is zero, so set it to 0:
  1806. if ((!m_pChildren  &&  m_pSourceElement->m_ulDuration == (UINT32)-1)  ||
  1807. 0 == ulNumChildrenWithNonEventBasedBegins)
  1808. {
  1809.     // /Checking 1st for explicit end or dur re-fixes PR 57150(excl)
  1810.     // which was broken by fix for PR 24046 (note: PR 57150 has dur=x
  1811.     // *and* endsync="all" which is a strange thing to author):
  1812.     if (!m_pSourceElement->m_bHasExplicitDur  &&
  1813.     !m_pSourceElement->m_bHasExplicitEnd)
  1814.     {
  1815. m_pSourceElement->m_ulDuration = 0;
  1816.     }
  1817.     // /Helps fix PR 62688(excl version): if all children are
  1818.     // event-begun and there is at least one child, and endsync="all",
  1819.     // then we have an indefinite duration until all child ends resolve:
  1820.     if (m_pChildren  &&  SMILEventSourceAll ==
  1821.     m_pSourceElement->m_nEndsyncEventSourceTag  &&
  1822.     // /Ignore endsync if it has explicit end or dur:
  1823.     !m_pSourceElement->m_bHasExplicitDur  &&
  1824.     !m_pSourceElement->m_bHasExplicitEnd)
  1825.     {
  1826. m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
  1827.     }
  1828. }
  1829. if (m_pSourceElement->m_ulDuration != (UINT32)-1)
  1830. {
  1831.     setDuration(m_pSourceElement->m_ulDuration);
  1832. #if 20011024
  1833.     // /Fixes PR 61174(version1) and excl version of PR 56686
  1834.     // (version1): we know our duration already, so let's declare it
  1835.     // resolved so we get added to our parent (in case none of our
  1836.     // children have scheduled begin times in which case our
  1837.     // ::addDuration() would not get called up front and the overall
  1838.     // presentation would not include our duration at first):
  1839.     if (m_pSourceElement->m_bHasExplicitDur  ||
  1840.     m_pSourceElement->m_bHasExplicitEnd  ||
  1841.     // /For PR 62688(excl version) and other endsync="all" bugs:
  1842.     SMILEventSourceAll ==
  1843.     m_pSourceElement->m_nEndsyncEventSourceTag)
  1844.     {
  1845. // /Be sure not to override a shorter duration that may have
  1846. // been imposed on us by our parent:
  1847. if (!m_bDurationSet  ||
  1848. !m_pSourceElement->m_bAddDurationAlreadyDone)
  1849. {
  1850.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  1851.     m_pSourceElement->getPureDuration());
  1852.     HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  1853.     durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  1854. }
  1855. HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
  1856.     }
  1857. #endif
  1858. }
  1859.     }
  1860.     else 
  1861. // /Let's not claim that the delay is set when we still
  1862. // are awaiting a delay (begin) event; we *do* need to
  1863. // add the delay of this to the event's begin offset.
  1864. // This is done by setting the new "m_bNonEventDelaySet"
  1865. // variable to TRUE and leaving m_bDelaySet to FALSE
  1866. // until the ElementResolved() call sets it to true:
  1867.     {
  1868. // /Parent calls setDelay before we get to ElementResolved,
  1869. // thus m_bDelaySet should never be TRUE if we have a
  1870. // delay event:
  1871. HX_ASSERT(!m_bDelaySet);
  1872. m_bNonEventDelaySet = TRUE; //ElementResolved will look at this.
  1873. m_ulNonEventDelay = ulDelay;
  1874.     }
  1875.     
  1876.     if(m_pDependent && m_bDurationSet)
  1877.     {
  1878. adjustDependentDuration(m_pDependent);
  1879. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1880. ULONG32 ulTotalDelay = 0;
  1881. if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1882. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1883. {
  1884.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1885. }
  1886. if (HXR_OK !=
  1887. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1888. {
  1889.     goto doneSettingDependent;
  1890. }
  1891. #else
  1892. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1893. m_pSourceElement->m_ulDuration;
  1894. // /Helps fix PR 6XXXX(excl version): if delay is already packed
  1895. // into the duration, then don't count it twice (as can happen in
  1896. // <seq><excl begin="1s">...</excl><excl begin="1s" ...):
  1897. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1898. {
  1899.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1900. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  1901.     {
  1902. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1903. ulTotalDelay);
  1904. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1905. ulTotalDelay)
  1906. {
  1907.     ulTotalDelay -=
  1908.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1909. }
  1910.     }
  1911. }
  1912. #endif
  1913. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1914. {
  1915.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1916.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1917. }
  1918. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  1919.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  1920.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  1921.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  1922.     ::fprintf(f1, "nt%s:CSmilTimelineExcl::setDelay(%lu): to %lu;"
  1923.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  1924.     ulDelay, m_pSourceElement->m_ulDelay,
  1925.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  1926.     ::fclose(f1); 
  1927.     bFirstTimeAddDurDebugout = FALSE; 
  1928. #endif 
  1929.  
  1930. // /XXXEH- TODO: figure out if we need to claim this is being set
  1931. // by "parent" (which is really time base) so clip-begin-like
  1932. // action can occur; I don't think so, however:
  1933. m_pDependent->setDelay(ulTotalDelay, FALSE);
  1934.     }
  1935. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1936. doneSettingDependent:
  1937. #endif
  1938.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1939. }
  1940. void
  1941. CSmilTimelineExcl::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
  1942.   BOOL bDurationExtendingDueToPause)
  1943. {
  1944.     if (bDurationExtendingDueToPause)
  1945.     {
  1946. // /Need to handle this case:
  1947. HX_ASSERT(!bDurationExtendingDueToPause);
  1948.     }
  1949.     setParExclDuration(ulDuration, bSetFromParent);
  1950. }
  1951. void
  1952. CSmilTimelineExcl::setMaxDuration(UINT32 ulMaxDuration)
  1953. {
  1954.     setParExclMaxDuration(ulMaxDuration);
  1955. }
  1956. void 
  1957. CSmilTimelineExcl::resetDelay(UINT32 ulDelay)
  1958. {
  1959.     INT32 lAdjustedDelay = 0;
  1960.     UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;
  1961.     if(m_pSourceElement->m_bBeginOffsetSet)
  1962.     {
  1963. lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
  1964. m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
  1965.     }
  1966.     else
  1967.     {
  1968. m_pSourceElement->m_ulDelay = ulDelay;
  1969.     }
  1970.     if(m_pChildren)
  1971.     {
  1972. CHXSimpleList::Iterator i = m_pChildren->Begin();
  1973. for(; i != m_pChildren->End(); ++i)
  1974. {
  1975.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  1976.     // /Don't set delay of children with no valid begin time; the
  1977.     // default begin of an excl child is "indefinite".  Note that
  1978.     // sync-arc begins of elements that are skipped during this
  1979.     // delay-setting-by-parent operation will be OK when they
  1980.     // resolve because the resolved time has the delay built in:
  1981.     // /Note: tested this with <a> child and it works fine,
  1982.     if (pElement->m_pSourceElement  &&
  1983.     (pElement->m_pSourceElement->m_bBeginOffsetSet
  1984. #if defined(XXXEH_HANDLE_MULTIPLE_EXCL_CHILD_SCHEDULED_BEGINS)
  1985.  /*can't do this fix yet because excl child w/beginOffset>0 must wait*/
  1986. // /If parent excl begins on event, child with non-
  1987. // event begin time won't yet have beginOffsetSet;
  1988. // fixes PR 56686(version 7 and 8):
  1989. || pElement->m_pSourceElement->
  1990. m_bHasAtLeastOneNonEventBasedBegin) )
  1991. #else
  1992. // Fixes PR 86106(version2): if this excl is in
  1993. // 2nd or subsequent child of seq then any updates to
  1994. // any prior sibling's duration wasn't causing this
  1995. // excl to adjust its children's delays accordingly.
  1996. // Now, we do so if and only if m_bDelaySet and has
  1997. // a non-event-based begin:
  1998. ||  pElement->m_bDelaySet  &&
  1999. pElement->m_pSourceElement->
  2000. m_bHasAtLeastOneNonEventBasedBegin 
  2001. ) )
  2002. #endif
  2003.     {
  2004. pElement->resetDelay(m_pSourceElement->m_ulDelay);
  2005.     }
  2006.     // /else leave delay unresolved.
  2007. }
  2008.     }
  2009.     // /To fix PR 59851(seq of excls), we need to update our next-in-seq
  2010.     // (m_pDependent) as well as make sure sync-arc listeners know we've
  2011.     // changed our overall time bounds delay as well;
  2012.     if (m_pDependent && m_bDurationSet  &&
  2013.     ulPriorDelay != m_pSourceElement->m_ulDelay)
  2014.     {
  2015. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2016. ULONG32 ulTotalDelay = 0;
  2017. if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  2018. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2019. {
  2020.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  2021. }
  2022. if (HXR_OK !=
  2023. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  2024. {
  2025.     goto doneSettingDependent;
  2026. }
  2027. #else
  2028. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  2029. m_pSourceElement->m_ulDuration;
  2030. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2031. {
  2032.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  2033. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  2034.     {
  2035. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2036. ulTotalDelay);
  2037. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2038. ulTotalDelay)
  2039. {
  2040.     ulTotalDelay -=
  2041.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2042. }
  2043.     }
  2044. }
  2045. #endif
  2046. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  2047. {
  2048.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  2049.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  2050. }
  2051.  
  2052. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  2053.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  2054.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  2055.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  2056.     ::fprintf(f1, "nt%s:CSmilTimelineExcl::resetDelay(%lu):from %lu to %lu;"
  2057.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  2058.     ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
  2059.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  2060.     ::fclose(f1); 
  2061.     bFirstTimeAddDurDebugout = FALSE; 
  2062. #endif 
  2063. m_pDependent->resetDelay(ulTotalDelay);
  2064. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2065. doneSettingDependent:
  2066. #endif
  2067. // /(Added while fixing PR 59851) Let others know our begin time changed:
  2068. m_pParser->m_pTimelineElementManager->notify(m_pID);
  2069.     }
  2070. }
  2071. void 
  2072. CSmilTimelineExcl::adjustDuration()
  2073. {
  2074.     BOOL    bReset = FALSE;
  2075.     UINT32  ulDuration = 0;
  2076.     BOOL    bDurationSet = FALSE;
  2077.     BOOL    bEndsyncIdDurationFound = FALSE; // /For endsync="[Some ID]"
  2078.     // /Fixes excl version of PR 50676 (Added during fix for PR 59584):
  2079.     ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  2080.     if (!m_bDurationSet)
  2081.     {
  2082. // /NOTE: If this has children who have not yet resolved their begin
  2083. // times (which is why we're in this if(), then other children whose
  2084. // durations have extended due to pausing will have no effect on
  2085. // this parent.  We need to let this parent update its duration
  2086. // accordingly (and its parents' durs as well).
  2087. goto cleanup;
  2088.     }
  2089.     if(m_pChildren)
  2090.     {
  2091. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2092. for(; i != m_pChildren->End(); ++i)
  2093. {
  2094.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2095.     // /Checking this fixes excl version of PR 69290: if child duration
  2096.     // isn't set yet, don't use it here:
  2097.     if (!pElement->m_bDurationSet)
  2098.     {
  2099. continue;
  2100.     }
  2101.     HX_ASSERT((UINT32)-1 != pElement->m_pSourceElement->m_ulDuration);
  2102.     // /Make sure we take endsync into account here:
  2103.     if (SMILEventSourceFirst == m_pSourceElement->m_nEndsyncEventSourceTag)
  2104.     {
  2105. if (!bDurationSet)
  2106. {
  2107.     ulDuration = pElement->m_pSourceElement->m_ulDuration;
  2108. }
  2109. else
  2110. {
  2111.          ulDuration = (ulDuration < pElement->m_pSourceElement->m_ulDuration) ?
  2112.     ulDuration : pElement->m_pSourceElement->m_ulDuration;
  2113. }
  2114. bDurationSet = TRUE;
  2115.     }
  2116.     else if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
  2117.     {
  2118. if (pElement->m_pSourceElement->m_pNode  &&
  2119. m_pSourceElement->m_EndsyncEventSourceID ==
  2120. pElement->m_pSourceElement->m_pNode->m_id)
  2121. {
  2122.     ulDuration = pElement->m_pSourceElement->m_ulDuration;
  2123.     bEndsyncIdDurationFound = TRUE;
  2124.     bDurationSet = TRUE;
  2125. }
  2126.     }
  2127.     // /This else-if block fixes problem in PR 62688 repro case where
  2128.     // restarting a child, prior to all children playing, caused excl
  2129.     // to resolve its dur as if it were endsync="last":
  2130.     else if (SMILEventSourceAll ==
  2131.     m_pSourceElement->m_nEndsyncEventSourceTag)
  2132.     {
  2133. if (m_pChildren  &&
  2134. m_nDurationAdded >= m_pChildren->GetCount())
  2135. {
  2136.          ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
  2137.     ulDuration : pElement->m_pSourceElement->m_ulDuration;
  2138.     bDurationSet = TRUE;
  2139. }
  2140. else
  2141. {
  2142.     // /Don't adjust duration until all child durs are in:
  2143.     goto cleanup;
  2144. }
  2145.     }
  2146.     else // /For "last", use the largest child duration:
  2147.     {
  2148. ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
  2149. ulDuration : pElement->m_pSourceElement->m_ulDuration;
  2150. bDurationSet = TRUE;
  2151.     }
  2152.     // /Fixes PR 50806 (excl versions 1 & 2): if this has "min"
  2153.     // attribute set, ulDuration shouldn't be less regardless
  2154.     // of endSync:
  2155.     if (m_pSourceElement->m_ulMinActiveDur > ulDuration)
  2156.     {
  2157. ulDuration = m_pSourceElement->m_ulMinActiveDur;
  2158.     }
  2159. }
  2160. // /!bDurationSet happens in PR 50588 (case 2: begin="x.end"), when
  2161. // child has begun playing but has not yet resolved its duration:
  2162. if (!bDurationSet)
  2163. {   HX_ASSERT(bDurationSet  &&  "contact-ehodge");
  2164.     goto cleanup;
  2165. }
  2166. if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
  2167.     if (!bEndsyncIdDurationFound)
  2168.     {
  2169. goto cleanup; // /That id'd child not added to timeline yet.
  2170.     }
  2171. //check m_ulAuthoredDur here:
  2172. if (!m_pSourceElement->m_bHasExplicitEnd  &&
  2173. !m_pSourceElement->m_bHasExplicitDur)
  2174.     m_pSourceElement->m_ulDuration = ulDuration;
  2175. }
  2176.     
  2177. // /Moved this out of the above if() so it gets called every time, to
  2178. // fix PR 6XXX? and re-fix PR 55117: we should always give our parents
  2179. // a chance to set the outer-time-container duration so it can (re)-
  2180. // state to the core what the group duration should be:
  2181. if(m_pParent)
  2182. {
  2183.     m_pParent->adjustDuration();
  2184. }
  2185. // /Moved this out to happen all the time, too:
  2186. if (m_pDependent)
  2187. {
  2188. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2189.     ULONG32 ulTotalDelay = 0;
  2190.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  2191.   m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2192.     {
  2193. HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  2194.     }
  2195.     if (HXR_OK != m_pSourceElement->getCurrentScheduledStopTime(
  2196.     ulTotalDelay))
  2197.     {
  2198. goto doneSettingDependent;
  2199.     }
  2200. #else
  2201.     ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  2202.     m_pSourceElement->m_ulDuration;
  2203.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2204.     {
  2205. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  2206. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  2207. {
  2208.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2209.     ulTotalDelay);
  2210.     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2211.     ulTotalDelay)
  2212.     {
  2213. ulTotalDelay -=
  2214. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2215.     }
  2216. }
  2217.     }
  2218. #endif
  2219.     if (WAY_IN_THE_FUTURE < ulTotalDelay)
  2220.     {
  2221. // /XXXEH- If delay is greater than this, I want to know:
  2222. HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  2223. ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  2224.     }
  2225. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  2226. {
  2227. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  2228. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  2229. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  2230. ::fprintf(f1, "nt%s:CSmilTimelineExcl::adjustDuration();tresetting dependent (%s)'s delay to %lun",
  2231. (const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
  2232. ::fclose(f1);
  2233. bFirstTimeAddDurDebugout = FALSE;
  2234. }
  2235. #endif
  2236.     m_pDependent->resetDelay(ulTotalDelay);
  2237. }
  2238. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2239. doneSettingDependent:
  2240. ;
  2241. #endif
  2242.     }
  2243.     // /Fixes PR 69410 (with outer excl): do this no matter what, even if
  2244.     // prior < ulDur; resumed element in excl should extend this excl but
  2245.     // we've already told the core to limit the presentation duration,
  2246.     // so extend it here as needed:
  2247.     // /(Added while fixing PR 59584): if our duration got reduced, we need to
  2248.     // possibly constrain our children:
  2249.     {
  2250. // /For PR 62688 & PR 59584: remove check for ulPriorDuration being
  2251. // WAY_IN_THE_FUTURE since PR 50676 works without it and there are
  2252. // cases where our dur may re-resolve, & updating children is needed:
  2253. // This group's outer time container, if this is one, needs
  2254. // to set the duration if its dur is longer than its group's so far
  2255. // or if its previous duration was unresolved and now is resolved:
  2256. if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  2257. {
  2258.     if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  2259.     m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  2260.     m_pSourceElement->m_pNode->
  2261. /*OK[]*/     m_pParent->m_bIsOuterWrapperTimeContainer) )
  2262.     {
  2263. // /The group duration should be the duration of this
  2264. // outer-most time container:
  2265. HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  2266. resolveGroupDurToOuterTimeContainerDur(
  2267. m_pSourceElement->m_pNode->m_nGroup,
  2268. m_pSourceElement->m_ulDuration);
  2269.     }
  2270. }
  2271. if(m_pChildren)
  2272. {
  2273.     // /Accounting for begin offset of this helps fix PR 65741(excl)
  2274.     // where excl w/begin="5s' was including that 5s in dur passed
  2275.     // to children, thus children were playing 5s too long:
  2276.     ULONG32 ulSyncBaseDurationForChildren =
  2277.     m_pSourceElement->m_ulDuration;
  2278.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  2279.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2280.     {
  2281. HX_ASSERT(ulSyncBaseDurationForChildren >=
  2282. m_pSourceElement->m_ulBeginOffsetFromSyncBase);
  2283. if (ulSyncBaseDurationForChildren >=
  2284. m_pSourceElement->m_ulBeginOffsetFromSyncBase)
  2285. {
  2286.     ulSyncBaseDurationForChildren -=
  2287.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2288. }
  2289.     }
  2290.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  2291.     for(; i != m_pChildren->End(); ++i)
  2292.     {
  2293. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2294. if (pElement->m_pSourceElement  &&
  2295. pElement->m_pSourceElement->m_ulDuration >
  2296. m_pSourceElement->m_ulDuration)
  2297. {
  2298.     pElement->setDuration(ulSyncBaseDurationForChildren, TRUE);
  2299. }
  2300.     }
  2301. }
  2302.     }
  2303. cleanup:
  2304.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  2305.     return;
  2306. }
  2307. void 
  2308. CSmilTimelineExcl::addDuration(UINT32 ulDuration,
  2309.       UINT32 ulDelay,
  2310.       UINT32 ulChildDelayBeyondStartOfThis, 
  2311.       const char* pElementID)
  2312. {
  2313.     BOOL bHandled = FALSE;
  2314.     UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  2315. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  2316.     {
  2317. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  2318. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  2319. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  2320. ::fprintf(f1, "CSmilTimelineExcl{%s}::addDuration(dur=%lu, delay=%lu, "
  2321. "childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sEn",
  2322. (const char*)m_pID, ulDuration, ulDelay,
  2323. ulChildDelayBeyondStartOfThis, pElementID,
  2324. m_bDurationSet?"TRU":"FALS");
  2325. ::fclose(f1);
  2326. bFirstTimeAddDurDebugout = FALSE;
  2327.     }
  2328. #endif
  2329.     // /If we're inside a seq, our true "sync base" is not the seq but rather
  2330.     // the prievious seq sibling (if any).  We need to adjust the ulDelay, if
  2331.     // we're in a seq, down to just ulChildDelayBeyondStartOfThis, which is
  2332.     // the delay from the prior sibling, not from the seq:
  2333.     ULONG32 ulDelayBeyondSyncBase = 0;
  2334.     SMILNode* pSyncBaseNode = NULL;
  2335.     if (m_pSourceElement->m_pNode)
  2336.     {
  2337. pSyncBaseNode = m_pParser->getSyncAncestor(
  2338.     m_pSourceElement->m_pNode);
  2339.     }
  2340.     if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
  2341.     {
  2342. HX_ASSERT(pSyncBaseNode  &&  pSyncBaseNode->m_pElement);
  2343.     }
  2344.     // /Do this for all time containers (for part of PR52110 post-fix-delay-
  2345.     // offset-bug):
  2346.     else
  2347.     {
  2348. ulDelayBeyondSyncBase = ulChildDelayBeyondStartOfThis;
  2349.     }
  2350.     BOOL bSetChildCurEndClippedByParent = FALSE;
  2351.     BOOL bSetCompletelyRemovedFromTimeline = FALSE;
  2352.     BOOL bIsCurChildsFirstAddDuration = FALSE;
  2353.     ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
  2354.     if (!(*m_pChildDurAddedMap)[pElementID])
  2355.     {
  2356. bIsCurChildsFirstAddDuration = TRUE;
  2357.     }
  2358.     else
  2359.     {
  2360. ulCurChildPriorAddedDuration =
  2361. (ULONG32)((*m_pChildDurAddedMap)[pElementID]);
  2362.     }
  2363.     ULONG32 ulActualDurBeyondSyncBase =
  2364.     ulDuration + ulDelayBeyondSyncBase - ulChildDelayBeyondStartOfThis;
  2365. // /XXXEH-20020106-test:    HX_ASSERT(WAY_IN_THE_FUTURE >= ulActualDurBeyondSyncBase);
  2366.     // /Start of fix for PR 55117: explicit dur or end on par should not be
  2367.     // overridden by some punk child's dur; if this has an explicit
  2368.     // end or dur, don't do anything to its duration based on children durs:
  2369.     // /XXXEH- TODO: determine what wins between endsync VS either end or dur
  2370.     // if both are specified; here, I assume end|dur wins over endsync:
  2371.     if (m_pSourceElement->m_bHasExplicitDur  ||
  2372.     m_pSourceElement->m_bHasExplicitEnd)
  2373.     {
  2374. if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
  2375. (!m_bDurationSet  ||
  2376. !m_pSourceElement->m_bAddDurationAlreadyDone) )
  2377. {
  2378.     HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  2379.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  2380.     m_pSourceElement->getPureDuration());
  2381.     durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  2382. }
  2383. // /Helps fix PR 6XXXZ (PR 55117 revisited): par in seq where par has explicit dur and
  2384. // children all have smaller durations, we need to give outer time
  2385. // container a chance to hold the presentation open; this is needed
  2386. // when this par is last one in presentation.  (Note: body doesn't set
  2387. // the presentation time during createElements() phase because it
  2388. // doesn't have m_pHandler yet then):
  2389. adjustDuration();
  2390. bHandled = TRUE;
  2391.     }
  2392.     // /Fixes SMIL 1.0's endsync="id(xyz)" and enables SMIL 2.0's
  2393.     // id-based endsync: endsync="xyz":
  2394.     else if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
  2395.     {
  2396. if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
  2397.         !strcmp(m_pSourceElement->m_EndsyncEventSourceID,pElementID))
  2398. {
  2399.     // /Don't just use ulDuration in case child has a begin offset
  2400.     // or otherwise has a delay beyond this's delay.
  2401.     m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
  2402.     durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  2403.     bHandled = TRUE;
  2404. }
  2405.     }
  2406.     else if(m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceAll)
  2407.     {
  2408. // /Hold excl open until all children have had a chance to begin;
  2409. // leave the excl's duration unresolved awaiting the final child's
  2410. // call to "addDuration" (which may never come if child's begin
  2411. // never resolves):
  2412. // /Helps fix PR 62688(excl version): first, check if all children
  2413. // have resolved already; if so, then duration is set so we can't
  2414. // extend it if begin is after parent excl ended:
  2415. if (m_nDurationAdded >= m_pChildren->GetCount()  &&
  2416. m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
  2417. {
  2418.     bSetChildCurEndClippedByParent = TRUE;
  2419.     HX_ASSERT(m_ulLastDuration == m_pSourceElement->m_ulDuration);
  2420.     if (m_ulLastDuration > ulChildDelayBeyondStartOfThis)
  2421.     {
  2422. // /Helps fix PR 50660 by removing PR 62688-fix code here that
  2423. // turned out to be unnecessary since code elsewhere completely
  2424. // fixes PR 62688.  Child should be allowed to extend its
  2425. // parent's duration except if it begins *after* its parent has
  2426. // already ended, which is how we got here, so do nothing.
  2427.     }
  2428.     else // /Begin offset is beyond parent's end, so remove it:
  2429.     // helps fix PR 62688(excl) (endsync="all" version of PR 64158)
  2430.     {
  2431. bSetCompletelyRemovedFromTimeline = TRUE;
  2432. HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  2433. handleTrackRemoval((const char*)pElementID,
  2434. (INT32)m_pSourceElement->m_pNode->m_nGroup);
  2435.     }
  2436. }
  2437. if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
  2438. !m_bFirstDurationHasBeenSet)
  2439. {
  2440.     m_ulFirstDuration = ulActualDurBeyondSyncBase;
  2441.     m_bFirstDurationHasBeenSet = TRUE;
  2442. }
  2443. if(ulActualDurBeyondSyncBase > m_ulLastDuration)
  2444. {
  2445.     m_ulLastDuration = ulActualDurBeyondSyncBase;
  2446. }
  2447. // /This helps fix PR 62688(par version): this is used to see if
  2448. // we've already resolved our duration (because all children have
  2449. // weighed in):
  2450. INT32 lTotalDurationsAddedIncludingThisOne = (INT32)m_nDurationAdded;
  2451. if (bIsCurChildsFirstAddDuration)
  2452. {
  2453.     lTotalDurationsAddedIncludingThisOne++;
  2454. }
  2455. if (lTotalDurationsAddedIncludingThisOne < m_pChildren->GetCount()  &&
  2456. // /To help fix PR 59584(excl version), only do this once:
  2457. WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
  2458. {
  2459.     // /XXXEH- need a better way, but for now let's say it's
  2460.     // resolved to a very big number until all children have
  2461.     // resolved begins:
  2462.     durationResolved(WAY_IN_THE_FUTURE, TRUE);
  2463. }
  2464.     }
  2465.     else if(m_pSourceElement->m_ulDuration == (UINT32)-1)
  2466.     {
  2467. // /Added delay to duration which works in:
  2468. // "BUG-20010430_endHappening2sTooEarlyForExclThatHas"...
  2469. // ..."2.7sBeginAndDurBasedOnChild(totalPresentationDur5.7s).smil":
  2470. m_pSourceElement->m_ulDuration = ulDuration + ulDelayBeyondSyncBase -
  2471. // /Works in excl version of
  2472. // "BUG-20010502(at0700hrs))_firstOu"..."2ndChildIsExcl.smil"
  2473. // /(NOTE: this will be non-zero in the case where the parent
  2474. // excl (this) has endsync="first" and is adding first child
  2475. // due to an event:
  2476. ulChildDelayBeyondStartOfThis;
  2477. m_ulFirstDuration = ulActualDurBeyondSyncBase;
  2478. m_bFirstDurationHasBeenSet = TRUE;
  2479. if (WAY_IN_THE_FUTURE >= m_pSourceElement->m_ulDuration  &&
  2480. !bIsCurChildsFirstAddDuration  &&
  2481. WAY_IN_THE_FUTURE <= ulCurChildPriorAddedDuration)
  2482. {
  2483.     HX_ASSERT(0); // /TESTING! PR 59584.
  2484.     // then don't do the next line (?):
  2485. }
  2486. m_ulLastDuration = ulActualDurBeyondSyncBase;
  2487.     }
  2488.     else
  2489.     // /An excl time container can only have one active track at a time,
  2490.     // but it can know that it will play subsequent ones if they have
  2491.     // resolved delays (which is how we entered this "else" block, so we
  2492.     // need to calculate the excl's duration as the latest that any resolved
  2493.     // element will play as far as we know at this point.  Excl's duration
  2494.     // in many cases will then vary as childrens' delays become resolved
  2495.     // over time:
  2496.     // /XXXEH- test this!!!  I left it the same as for Par, but we should
  2497.     // consider interrupt behavior of the excl's elements since one may
  2498.     // not start while another "uninterruptable" element is playing and
  2499.     // thus may not affect the excl's initial dur:
  2500.     {
  2501. m_pSourceElement->m_ulDuration = 
  2502.     (ulActualDurBeyondSyncBase > m_pSourceElement->m_ulDuration) ?
  2503.     ulActualDurBeyondSyncBase : m_pSourceElement->m_ulDuration;
  2504. // /XXXEH- TODO: handle m_ulFirst...etc. (or make sure they work) now
  2505. // that delay is being added (as it should be) to m_ulDuration, above:
  2506. if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
  2507. !m_bFirstDurationHasBeenSet)
  2508. {
  2509.     m_ulFirstDuration = ulActualDurBeyondSyncBase;
  2510.     m_bFirstDurationHasBeenSet = TRUE;
  2511. }
  2512. if(ulActualDurBeyondSyncBase > m_ulLastDuration)
  2513. {
  2514.     m_ulLastDuration = ulActualDurBeyondSyncBase;
  2515. }
  2516.     }
  2517.     if (!(*m_pChildDurAddedMap)[pElementID])
  2518.     {
  2519. m_nDurationAdded++;
  2520. (*m_pChildDurAddedMap)[pElementID] = (void*)ulActualDurBeyondSyncBase;
  2521.     }
  2522.     ULONG32 ulChildrenCount = m_pChildren->GetCount();
  2523.     // /Fixes PR 56481(excl version) find children that don't have a scheduled
  2524.     // begin, i.e., are awaiting an event to begin.  endsync="last" says to
  2525.     // ignore any children that never play, and we don't know if those
  2526.     // event-based begin children will play or not so ignore them for now,
  2527.     // and if they ever do begin, *then* re-compute this excl's duration:
  2528.     ULONG32 ulNonEventBasedBeginChildCount = 0;
  2529.     CSmilElement* pCurChildElem = NULL;
  2530.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  2531.     for(i; i != m_pChildren->End(); ++i)
  2532.     {
  2533. CSmilTimelineElement* pTmlnElement =
  2534. (CSmilTimelineElement*)(*i);
  2535. if (pTmlnElement  &&  pTmlnElement->m_pSourceElement)
  2536. {
  2537.     BOOL isCurAddDurElem = FALSE;
  2538.     if (!strcmp(pTmlnElement->m_pSourceElement->m_pNode->m_id,
  2539.     pElementID))
  2540.     {
  2541. isCurAddDurElem = TRUE;
  2542. pCurChildElem = pTmlnElement->m_pSourceElement;
  2543. if (bSetChildCurEndClippedByParent  &&  pCurChildElem)
  2544. {
  2545.     pCurChildElem->m_bCurEndClippedByParent = TRUE;
  2546. }
  2547. if (bSetCompletelyRemovedFromTimeline  &&  pCurChildElem)
  2548. {
  2549.     pCurChildElem->m_bInsertedIntoTimeline = FALSE;
  2550. }
  2551.     }
  2552.     if ((pTmlnElement->m_pSourceElement->
  2553.     m_bHasAtLeastOneNonEventBasedBegin  ||
  2554.     // /Do this so this par can re-resolve its duration if &
  2555.     // when an event-based-begin child gets added (and thus
  2556.     // technically now is a child with a clock-valued begin):
  2557.     isCurAddDurElem) )
  2558.     {
  2559. ulNonEventBasedBeginChildCount++;
  2560.     }
  2561. }
  2562.     }
  2563.     
  2564.     if (!bHandled  &&
  2565.     (m_nDurationAdded >= ulNonEventBasedBeginChildCount  &&
  2566.     // /If endsync is all, we need to wait for *all* to be added:
  2567.     (SMILEventSourceAll!=m_pSourceElement->m_nEndsyncEventSourceTag  ||
  2568.     m_nDurationAdded == ulChildrenCount) )  &&
  2569.     !m_bDurationEvent)
  2570.     {
  2571. BOOL bUpdateDurMightBeNeeded = FALSE;
  2572. // /Helps fix PR 62688(excl): if duration was set before, but only to
  2573. // hold the timeline open until all (or a particular) child duration
  2574. // became known, then we want to ignore the durationSet flag so that
  2575. // we call duartionResolved() instead of adjustDuration();
  2576. BOOL bIgnoreDurationSetFlag = bIsCurChildsFirstAddDuration  &&
  2577. (WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDelay +
  2578. m_pSourceElement->m_ulDuration);
  2579. // /First, if duration has already been set, then pElement must be an
  2580. // event-based-begin child that just resolved, so we need to reset
  2581. // our duration appropriately:
  2582. if (m_bDurationSet  &&  pCurChildElem  &&  !bIgnoreDurationSetFlag  &&
  2583. !pCurChildElem->m_bHasAtLeastOneNonEventBasedBegin)
  2584. {
  2585.     bUpdateDurMightBeNeeded = TRUE;
  2586. }
  2587. if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  2588.     SMILEventSourceFirst)
  2589. {
  2590.     if (bUpdateDurMightBeNeeded)
  2591.     {
  2592. if (ulActualDurBeyondSyncBase == m_ulFirstDuration)
  2593. {
  2594.     // /XXXEH- revisit now that addDuration accts for endsync:
  2595.     ULONG32 ulOldDur = m_pSourceElement->m_ulDuration;
  2596.     adjustDuration();
  2597.     HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulFirstDuration);
  2598.     // /Other half of fix for PR 50679: if updated duration
  2599.     // is less than prior dur, then update timeline element:
  2600.     if (ulOldDur > m_pSourceElement->m_ulDuration)
  2601.     {
  2602. // /Reset duration-set flag to FALSE since we want to
  2603. // override (reset) the dur now that this last child
  2604. // has been resolved (presumably after playback of
  2605. // this par began):
  2606. m_bDurationSet = FALSE;
  2607. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  2608.     }
  2609. }
  2610.     }
  2611.     else
  2612.     {
  2613. durationResolved(m_ulFirstDuration, TRUE);
  2614.     }
  2615. }
  2616. else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  2617.     SMILEventSourceLast)
  2618. {
  2619.     if (bUpdateDurMightBeNeeded)
  2620.     {
  2621. if (ulActualDurBeyondSyncBase == m_ulLastDuration)
  2622. {
  2623.     adjustDuration();
  2624. }
  2625.     }
  2626.     else
  2627.     {
  2628. // /Helps fix PR 59584(simplified): if we previously resolved
  2629. // our duration to "unresolved" to hold timeline open, then we
  2630. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  2631. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  2632. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  2633. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  2634. {
  2635.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  2636.     bIsCurChildsFirstAddDuration)
  2637.     {
  2638. // /See "part 2 of PR 79699" above; don't want to mess
  2639. // with this unless there's content that asserts here:
  2640. HX_ASSERT(m_bDurationSet);
  2641.     }
  2642.     adjustDuration();
  2643.     m_bDurationSet = FALSE;
  2644. }
  2645. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  2646. m_pSourceElement->getPureDuration());
  2647. // /To fix PR 59584(exclVersionSimplified, w/"last"), use
  2648. // m_pSourceE.'s dur, not m_ulLastDuration since latter may
  2649. // be wrong if some elements stopped early
  2650. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  2651.     }
  2652. }
  2653. else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
  2654.     SMILEventSourceAll)
  2655. {
  2656.     if (bUpdateDurMightBeNeeded)
  2657.     {
  2658. if (ulActualDurBeyondSyncBase == m_ulLastDuration)
  2659. {
  2660.     // /adjustDuration() assumes endsync=last which is OK
  2661.     // since we've got all durations:
  2662.     adjustDuration();
  2663. }
  2664.     }
  2665.     else
  2666.     {
  2667. // /Helps fix PR 59584(excl, simpl.): if we previously resolved
  2668. // our duration to "unresolved" to hold timeline open, then we
  2669. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  2670. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  2671. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  2672. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  2673. {
  2674.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  2675.     bIsCurChildsFirstAddDuration)
  2676.     {
  2677. // /See "part 2 of PR 79699" above; don't want to mess
  2678. // with this unless there's content that asserts here:
  2679. HX_ASSERT(m_bDurationSet);
  2680.     }
  2681.     adjustDuration();
  2682. }
  2683. HX_ASSERT(m_pSourceElement->m_ulDuration ==
  2684. m_pSourceElement->getPureDuration());
  2685. // /Reset duration-set flag to FALSE since we want to
  2686. // override (reset) the dur now that this last child has been
  2687. // resolved (presumably after playback of this par began):
  2688. m_bDurationSet = FALSE;
  2689. // /To fix PR 59584(exclVersionSimplified), use m_pSourceE.'s
  2690. // duration, not m_ulLastDuration since latter may be wrong
  2691. // if some elements stopped early:
  2692. durationResolved(m_pSourceElement->m_ulDuration, TRUE);
  2693.     }
  2694. }
  2695. else
  2696. {
  2697.     if (bUpdateDurMightBeNeeded)
  2698.     {
  2699. if (ulActualDurBeyondSyncBase == m_pSourceElement->m_ulDuration)
  2700. {
  2701.     adjustDuration();
  2702. }
  2703.     }
  2704.     else
  2705.     {
  2706. // /Helps fix PR 62688(excl version): if we previously resolved
  2707. // our duration to "unresolved" to hold timeline open, then we
  2708. // need to adjust our duration down from WAY_IN_THE_FUTURE:
  2709. if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
  2710. WAY_IN_THE_FUTURE == m_ulLastDuration  ||
  2711. m_pSourceElement->m_ulDuration != m_ulLastDuration)
  2712. {
  2713.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
  2714.     bIsCurChildsFirstAddDuration)
  2715.     {
  2716. // /See "part 2 of PR 79699" above; don't want to mess
  2717. // with this unless there's content that asserts here:
  2718. HX_ASSERT(m_bDurationSet);
  2719.     }
  2720.     adjustDuration();
  2721.     m_bDurationSet = FALSE;
  2722. }
  2723. HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulLastDuration);
  2724. durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  2725.     }
  2726. }
  2727. // /This if() block fixes PR 56686 (version 4) and
  2728. // PR 61174 (version 4): if time container has longer dur than its
  2729. // children and it is not a time-child of the <body>, then its dur
  2730. // was never getting accounted for, but now the outer time container
  2731. // sets the duration if its dur is longer than its group's so far;
  2732. // outer time contnr can only be a par if body has multiple children:
  2733. if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
  2734. {
  2735.     // /XXXEH- handle <body><switch><par> and <body><a><par>
  2736.     if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
  2737.     m_pSourceElement->m_pNode->m_pParent->m_tag  ||
  2738.     m_pSourceElement->m_pNode->
  2739. /*OK[]*/     m_pParent->m_bIsOuterWrapperTimeContainer) )
  2740.     {
  2741. UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
  2742. // /The group duration should be the duration of this
  2743. // outer-most time container:
  2744. HX_RESULT pnrs = m_pSourceElement->m_pHandler->
  2745. resolveGroupDurToOuterTimeContainerDur(
  2746. ulGroup, m_pSourceElement->m_ulDuration);
  2747.     }
  2748. }
  2749.     }
  2750. }
  2751. void
  2752. CSmilTimelineExcl::elementResolved(CSmilTimelineElement* pEventElement)
  2753. {
  2754.     parExclElementResolved(pEventElement);
  2755. }
  2756. void
  2757. CSmilTimelineExcl::durationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
  2758. {
  2759.     parExclDurationResolved(ulDuration, bUpdateChildren);
  2760. }
  2761. /***************************************************************************/
  2762. /*
  2763.  * CSmilTimelineAnchor methods
  2764.  */
  2765. CSmilTimelineAnchor::CSmilTimelineAnchor(CSmilElement* pSourceElement,
  2766.    CSmilParser* pParser):
  2767.     CSmilTimelineElement(pSourceElement, pParser)
  2768.     , m_nDurationAdded(0)
  2769. {
  2770. }
  2771. CSmilTimelineAnchor::~CSmilTimelineAnchor()
  2772. {
  2773. }
  2774. void
  2775. CSmilTimelineAnchor::elementResolved(CSmilTimelineElement* pEventElement)
  2776. {
  2777.     //First, let's see if we have a begin event to resolve:
  2778.     if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
  2779.     m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
  2780.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
  2781.     {
  2782. if(pEventElement->m_bDelaySet)
  2783. {
  2784.     //[SMIL 1.0 Compliance] Helps fix 14420:
  2785.     if (m_bNonEventDelaySet)
  2786.     {
  2787. //Add non-event delay to syncArc element's delay + clock offset:
  2788. LONG32 lSum =
  2789. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2790. m_pSourceElement->m_lBeginEventClockValue;
  2791. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2792. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2793. m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
  2794.     }
  2795.     else
  2796.     {
  2797. m_ulNonEventDelay = 0;
  2798. //Just set delay to syncArc element's delay:
  2799. //Do the following in case sum is negative; if so, we
  2800. // want to use zero.
  2801. LONG32 lSum =
  2802. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2803. // /Fixes case where anchor/area has begin="foo.begin+5s"
  2804. // we need to account for the 5s here:
  2805. m_pSourceElement->m_lBeginEventClockValue;
  2806. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2807. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2808. m_pSourceElement->m_ulDelay = (ULONG32)lSum;
  2809. // /Now, we need to set the vars that keep track of our
  2810. // offset from our syncBase element because isCurrentLink
  2811. // uses times relative to our syncBase:
  2812. SMILNode* pSyncNode = (!m_pParser? NULL :
  2813.        m_pParser->getSyncAncestor(m_pSourceElement->m_pNode));
  2814. HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
  2815. if (pSyncNode  &&  pSyncNode->m_pElement)
  2816.     ULONG32 ulSyncBaseDelay =
  2817.     pSyncNode->m_pElement->m_ulDelay;
  2818.     HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
  2819.     if ((UINT32)-1 != ulSyncBaseDelay  &&
  2820.     (UINT32)-1 != m_pSourceElement->m_ulDelay )
  2821.     { 
  2822. HX_ASSERT(m_pSourceElement->m_ulDelay >=
  2823. ulSyncBaseDelay);
  2824. m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase =
  2825. TRUE;
  2826. if (m_pSourceElement->m_ulDelay >= ulSyncBaseDelay)
  2827.     ULONG32 ulEffectiveBeginOffset =
  2828.     m_pSourceElement->m_ulDelay -
  2829.     ulSyncBaseDelay;
  2830.     m_pSourceElement->m_ulBeginOffsetFromSyncBase =
  2831.     ulEffectiveBeginOffset;
  2832. else
  2833.     m_pSourceElement->m_ulBeginOffsetFromSyncBase = 0;
  2834.     } 
  2835.     }
  2836.     m_bNonEventDelaySet = m_bDelaySet = TRUE;
  2837.     if(m_pChildren)
  2838.     {
  2839. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2840. for(; i != m_pChildren->End(); ++i)
  2841. {
  2842.     CSmilTimelineElement* pElement =
  2843.     (CSmilTimelineElement*)(*i);
  2844.     pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  2845. }
  2846.     }
  2847. }
  2848.     }
  2849.     else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
  2850.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
  2851.     {
  2852. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  2853. // essentially an unresolved end time, so we should not resolve
  2854. // based on it:
  2855. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  2856. pEventElement->m_pSourceElement->m_ulDuration)
  2857. {
  2858.     //[SMIL 1.0 Compliance] Helps fix 14420:
  2859.     if (m_bNonEventDelaySet)
  2860.     {
  2861. //Add non-event delay to syncArc element's delay + clock offset:
  2862. LONG32 lSum =
  2863. (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
  2864. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2865. // /Fixes begin="foo.end+5s"; 5s was being ignored:
  2866. m_pSourceElement->m_lBeginEventClockValue;
  2867. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2868. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2869. m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
  2870.     }
  2871.     else
  2872.     {
  2873. //Add non-event delay to syncArc element's delay + clock offset:
  2874. LONG32 lSum =
  2875. (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
  2876. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2877. // /Fixes PR 68495 begin="foo.end+5s"; 5s was ignored
  2878. // without the following:
  2879. m_pSourceElement->m_lBeginEventClockValue;
  2880. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2881. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2882. m_ulNonEventDelay = 0;
  2883. m_pSourceElement->m_ulDelay = (ULONG32)lSum;
  2884.     }
  2885.     m_bNonEventDelaySet = m_bDelaySet = TRUE;
  2886.     if(m_pChildren)
  2887.     {
  2888. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2889. for(; i != m_pChildren->End(); ++i)
  2890. {
  2891.     CSmilTimelineElement* pElement =
  2892.     (CSmilTimelineElement*)(*i);
  2893.     pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  2894. }
  2895.     }
  2896. }
  2897.     }
  2898.     
  2899.     //XXXEH-The following cases need to be tested!:
  2900.     if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
  2901.     m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
  2902.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  2903.     {
  2904. if(pEventElement->m_bDelaySet)
  2905. {
  2906.     LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2907.          m_pSourceElement->m_lEndEventClockValue;
  2908.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2909.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2910.     durationResolved((ULONG32)lSum);
  2911. }
  2912.     }
  2913.     else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
  2914.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  2915.     {
  2916. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  2917. // essentially an unresolved end time, so we should not resolve
  2918. // based on it:
  2919. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  2920. pEventElement->m_pSourceElement->m_ulDuration)
  2921. {
  2922.     LONG32 lSum =(LONG32)pEventElement->getDuration() +
  2923.     m_pSourceElement->m_lEndEventClockValue;
  2924.     // /If the event element has a delay, we need to add that:
  2925.     if(pEventElement->m_bDelaySet)
  2926.     {
  2927. lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
  2928. if (pEventElement->m_pSourceElement->m_bBeginOffsetSet)
  2929. {
  2930.     lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
  2931. }
  2932.     }
  2933.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2934.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2935.     durationResolved((ULONG32)lSum);
  2936. }
  2937.     }
  2938. }
  2939. void
  2940. CSmilTimelineAnchor::durationResolved(UINT32 ulDuration)
  2941. {
  2942.     if(!m_bDurationSet)
  2943.     {
  2944. m_bDurationSet = TRUE;
  2945. m_pSourceElement->m_ulDuration = ulDuration;
  2946.     }
  2947. }
  2948. CSmilTimelineAnimate::CSmilTimelineAnimate(CSmilElement* pSourceElement,
  2949.                                            CSmilParser* pParser)
  2950.     : CSmilTimelineElement(pSourceElement, pParser)
  2951. {
  2952. }
  2953. CSmilTimelineAnimate::~CSmilTimelineAnimate()
  2954. {
  2955. }
  2956. void CSmilTimelineAnimate::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
  2957.   BOOL bDurationExtendingDueToPause)
  2958. {
  2959.     if (!bSetFromParent)
  2960.     {
  2961.         CSmilTimelineElement::setDuration(ulDuration, bSetFromParent,
  2962.   bDurationExtendingDueToPause);
  2963.     }
  2964. }