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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: smltime.cpp,v 1.3.4.2 2004/07/13 23:02:47 ehodge Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. // system
  50. #include <time.h>
  51. // include
  52. #include "hxtypes.h"
  53. #include "hxwintyp.h"
  54. #include "hxcom.h"
  55. #include "hxxml.h"
  56. #include "smiltype.h"
  57. // pncont
  58. #include "hxslist.h"
  59. #include "hxmap.h"
  60. // pnmisc
  61. #include "hxwinver.h"
  62. // rnxmllib
  63. #include "hxxmlprs.h"
  64. // rmasmil
  65. #include "smlelem.h"
  66. #include "smlparse.h"
  67. #include "smltime.h"
  68. #include "smlprstime.h"
  69. // pndebug
  70. #include "debugout.h"
  71. #include "hxassert.h"
  72. #include "hxheap.h"
  73. #ifdef _DEBUG
  74. #undef HX_THIS_FILE
  75. static const char HX_THIS_FILE[] = __FILE__;
  76. #endif
  77. // /#define XXXEH_DEBUGOUT_ADDDURATION
  78. #if defined(XXXEH_DEBUGOUT_ADDDURATION)
  79. #define ADDDURATION_DEBUGOUT_STR_NEW_FILE   "w"
  80. #define ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE   "a+"
  81. static BOOL bFirstTimeAddDurDebugout = TRUE;
  82. #endif
  83. /*
  84.  * CSmilTimelineElementManager methods
  85.  */
  86. CSmilTimelineElementManager::CSmilTimelineElementManager():
  87.     m_pElementMap(NULL),
  88.     m_pNotifierMap(NULL)
  89. {
  90. }
  91. CSmilTimelineElementManager::~CSmilTimelineElementManager()
  92. {
  93.     HX_DELETE(m_pElementMap);
  94.     if(m_pNotifierMap)
  95.     {
  96. CHXMapStringToOb::Iterator i = m_pNotifierMap->Begin();
  97. for(; i != m_pNotifierMap->End(); ++i)
  98. {
  99.     CHXSimpleList* pList = (CHXSimpleList*)(*i);
  100.     delete pList;
  101. }
  102. HX_DELETE(m_pNotifierMap);
  103.     }
  104. }
  105. void
  106. CSmilTimelineElementManager::addTimelineElement(CSmilTimelineElement* pElement)
  107. {
  108.     if(!m_pElementMap)
  109.     {
  110. m_pElementMap = new CHXMapStringToOb;
  111.     }
  112.     (*m_pElementMap)[pElement->m_pID] = pElement;
  113. }
  114. CSmilTimelineElement*
  115. CSmilTimelineElementManager::getTimelineElement(const char* pID)
  116. {
  117.     CSmilTimelineElement* pElement = NULL;
  118.     if(m_pElementMap)
  119.     {
  120. m_pElementMap->Lookup(pID, (void*&)pElement);
  121.     }
  122.     return pElement;
  123. }
  124. void
  125. CSmilTimelineElementManager::addNotification(const char* pID,
  126.      CSmilTimelineElement* pElement)
  127. {
  128.     if(!m_pNotifierMap)
  129.     {
  130. m_pNotifierMap = new CHXMapStringToOb;
  131.     }
  132.     CHXSimpleList* pNotifyList = NULL;
  133.     if(!m_pNotifierMap->Lookup(pID, (void*&)pNotifyList))
  134.     {
  135. pNotifyList = new CHXSimpleList;
  136. (*m_pNotifierMap)[pID] = pNotifyList;
  137.     }
  138.     pNotifyList->AddTail(pElement);
  139. }
  140. void
  141. CSmilTimelineElementManager::notify(const char* pID)
  142. {
  143.     CHXSimpleList* pNotifyList = NULL;
  144.     if(m_pNotifierMap)
  145.     {
  146. if(m_pNotifierMap->Lookup(pID, (void*&)pNotifyList))
  147. {
  148.     CSmilTimelineElement* pDependentElement = NULL;
  149.     if(m_pElementMap->Lookup(pID, (void*&)pDependentElement))
  150.     {
  151. CHXSimpleList::Iterator i = pNotifyList->Begin();
  152. for(; i != pNotifyList->End(); ++i)
  153. {
  154.     CSmilTimelineElement* pElement = 
  155. (CSmilTimelineElement*)(*i);
  156.     pElement->elementResolved(pDependentElement);
  157. }
  158.     }
  159. }
  160.     }
  161. }
  162. void
  163. CSmilTimelineElementManager::resetTimeline()
  164. {
  165.     if(m_pElementMap)
  166.     {
  167. CHXMapStringToOb::Iterator i = m_pElementMap->Begin();
  168. for(; i != m_pElementMap->End(); ++i)
  169. {
  170.     CSmilTimelineElement* pElement = 
  171. (CSmilTimelineElement*)(*i);
  172.     pElement->reset();
  173. }
  174.     }
  175. }
  176. /*
  177.  * CSmilTimelineElement methods
  178.  */
  179. CSmilTimelineElement::CSmilTimelineElement(CSmilElement* pSourceElement,
  180.    CSmilParser* pParser):
  181.     m_pSourceElement(pSourceElement),
  182.     m_pParser(pParser),
  183.     m_bDurationSet(FALSE),
  184.     m_bMaxDurationSet(FALSE),
  185.     m_bDelaySet(FALSE),
  186.     m_bDontResetDuration(FALSE),
  187.     m_bNonEventDelaySet(FALSE),
  188.     m_ulNonEventDelay((UINT32)-1),
  189.     m_bDelayEvent(FALSE),
  190.     m_bDurationEvent(FALSE),
  191.     m_pChildDurAddedMap(NULL),
  192.     m_bHasChildWithScheduledBegin(FALSE),
  193.     m_bInElementResolved(FALSE),
  194.     m_pParent(NULL),
  195.     m_pChildren(NULL),
  196.     m_pDependent(NULL)
  197. {
  198.     m_pID = new char[pSourceElement->m_pNode->m_id.GetLength() + 1];
  199.     strcpy(m_pID, (const char*)m_pSourceElement->m_pNode->m_id); /* Flawfinder: ignore */
  200.     //[SMIL 1.0 Compliance] Helps fix PR 26471:
  201.     // /XXXEH- TODO: this is probably one of the places where
  202.     // endsync="media" is handled.  We probably don't want to do the
  203.     // following if() statement if endsync is NOT media on the parent
  204.     // of an anchor|area element:
  205.     if (SMILAnchor != m_pSourceElement->m_pNode->m_tag  &&
  206.     SMILArea != m_pSourceElement->m_pNode->m_tag)
  207.     {
  208. m_pParser->m_pTimelineElementManager->addTimelineElement(this);
  209.     }
  210.     if(pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin ||
  211. pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd ||
  212. pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)
  213.     {
  214. m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_BeginEventSourceID,
  215.     this);
  216. // /If we've already got a resolved begin, then we don't want to claim
  217. // that we're awaiting this sync-arc begin (as can happen if
  218. // begin="0s; x.begin+4s")
  219. if (!pSourceElement->m_bBeginOffsetSet)
  220. {
  221.     m_bDelayEvent = TRUE;
  222. }
  223.     }
  224.     if(pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin ||
  225. pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd ||
  226. pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)
  227.     {
  228. m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_EndEventSourceID,
  229.     this);
  230. // /If we've already got a resolved end, then we don't want to claim
  231. // that we're awaiting this sync-arc end (as can happen if
  232. // end="10s; x.begin+14s")
  233. if (!pSourceElement->m_bEndOffsetSet)
  234. {
  235.     m_bDurationEvent = TRUE;
  236. }
  237.     }
  238.     if(pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
  239.     {
  240. m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_EndsyncEventSourceID,
  241.     this);
  242. m_bDurationEvent = TRUE;
  243.     }
  244.     m_pChildDurAddedMap = new CHXMapStringToOb();
  245.     // /XXXEH- TODO: make sure this is what we want to do:
  246.     // /Get next resolved time, if any.  If none are found in a non-empty
  247.     // begin-time list, then treat this as a delayed event:
  248.     if (NULL != pSourceElement->m_pBeginTimeList  &&
  249.     !pSourceElement->m_pBeginTimeList->IsEmpty())
  250.     {
  251. SmilTimeValue* pNextResolvedTimeValue = NULL;
  252. HX_RESULT rettimeval = HXR_OK;
  253. rettimeval = pSourceElement->getNextResolvedTimeValue(
  254. pNextResolvedTimeValue,
  255. // /XXXEH- TODO: make sure we don't want to input cur time here;
  256. // is it possible that we'd get here after time 0 in the parent
  257. // timeline???  I don't think so...:
  258. SMILTIME_NEGATIVE_INFINITY,
  259. SMILTIME_NEGATIVE_INFINITY,
  260. SmilBeginTimeList,
  261. /* Don't need list of resolved times:*/ NULL);
  262. if (!SUCCEEDED(rettimeval)  ||  NULL == pNextResolvedTimeValue)
  263. {
  264.     // /Has no resolved time yet so must be awaiting an event:
  265.     m_bDelayEvent = TRUE;
  266. }
  267.     }
  268. }
  269. CSmilTimelineElement::~CSmilTimelineElement()
  270. {
  271.     delete m_pChildren;
  272.     delete[] m_pID;
  273.     HX_DELETE(m_pChildDurAddedMap);
  274. }
  275. void
  276. CSmilTimelineElement::reset()
  277. {
  278.     m_bDelaySet = FALSE;
  279.     m_bNonEventDelaySet = FALSE;
  280.     m_ulNonEventDelay = (UINT32)-1;
  281.     m_bDurationSet = FALSE;
  282.     m_bMaxDurationSet = FALSE;
  283.     // /XXXEH- do we really want to do this? Find a way to test this:
  284. #if defined(XXXEH_NEEDS_TESTING)
  285.     HX_DELETE(m_pChildDurAddedMap); // /start fresh
  286. #endif
  287. }
  288. void
  289. CSmilTimelineElement::prepForRestart()
  290. {
  291.     m_bDelaySet = FALSE;
  292.     m_bNonEventDelaySet = FALSE;
  293.     m_ulNonEventDelay = (UINT32)-1;
  294. #if XXXEH_OLD_WAY_THAT_DIDNT_LET_SETDURATION_TAKE_CARE_OF_NEW_DUR
  295.     if (((UINT32)-1) != m_pSourceElement->m_ulOriginalDuration)
  296.     {
  297. resetDuration(m_pSourceElement->m_ulOriginalDuration);
  298.     }
  299.     // /Note: leave m_bDurationSet & m_bMaxDurationSet alone for restart
  300. #else
  301.     //...But if we're restarting, our duration may be different and this
  302.     // gets handled in CSmilTimelineElement::setDuration():
  303.     m_bDurationSet = FALSE;
  304.     // /Fixes PR 54704: if we don't reset this in concert with resetting
  305.     // m_bDurationSet, above, then ancestorEventsAreResolved() will fail
  306.     // when a re-insertTimelineElement() call on this occurs:
  307.     m_bDurationEvent = FALSE;
  308. #endif
  309. }
  310. void 
  311. CSmilTimelineElement::setDelay(UINT32 ulDelay, BOOL bSetByParent)
  312. {
  313.     ULONG32 ulPreviouslySetDelay = m_pSourceElement->m_ulDelay;
  314.     ULONG32 ulPreviouslySetPureDuration = m_pSourceElement->getPureDuration();
  315. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  316.     {
  317. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  318. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  319. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  320. ::fprintf(f1, "CSmilTimelineElement{%s}::setDelay(delay=%lu, "
  321. "bSetByParent=%sE), prior delay=%lu, m_bDelaySet=%sEn",
  322. (const char*)m_pID, ulDelay,
  323. bSetByParent?"TRU":"FALS",
  324. ulPreviouslySetDelay,
  325. m_bDelaySet?"TRU":"FALS");
  326. ::fclose(f1);
  327. bFirstTimeAddDurDebugout = FALSE;
  328.     }
  329. #endif
  330.     if(!m_bDelaySet)
  331.     {
  332. // /For PR 59584: if we're just resolving this to let the
  333. // group duration "resolve" to unresolved, don't count begin:
  334. if(WAY_IN_THE_FUTURE <= ulDelay)
  335. {
  336.     HX_ASSERT(WAY_IN_THE_FUTURE >= ulDelay);
  337. }
  338. else if(!m_bDelayEvent)
  339. {
  340.     BOOL bDelayClippedDueToNegOffset = FALSE;
  341.     if(m_pSourceElement->m_bBeginOffsetSet)
  342.     {
  343. m_pSourceElement->m_ulDelay = ulDelay;
  344. // /Handle all cases so that we don't overflow:
  345. UINT32 ulPosOffset = m_pSourceElement->m_lBeginOffset > 0?
  346. m_pSourceElement->m_lBeginOffset : 0;
  347. UINT32 ulNegOffset = m_pSourceElement->m_lBeginOffset < 0?
  348. (UINT32)(-m_pSourceElement->m_lBeginOffset) : 0;
  349. UINT32 ulClippedAmt = 0;
  350. if (ulNegOffset > 0)
  351. {
  352.     m_pSourceElement->m_bNegBeginOffsetAlreadyUsed =
  353.     TRUE;
  354. }
  355. m_pSourceElement->m_ulDelay += ulPosOffset;
  356. if (m_pSourceElement->m_ulDelay >= ulNegOffset)
  357. {
  358.     m_pSourceElement->m_ulDelay -= ulNegOffset;
  359. }
  360. else
  361. {
  362.     // /If set by parent, then we want to use the entire
  363.     // negative offset FROM OUR PARENT's BEGIN which already
  364.     // has the delay in it, so <par begin="2s"><ref begin=
  365.     // "-3s" ...> would begin the ref at 2s w/3s clip-begin:
  366.     ulClippedAmt = bSetByParent? ulNegOffset : ulNegOffset -
  367.     m_pSourceElement->m_ulDelay;
  368.     // /If clip-begin is invalid, set it otherwise add to it:
  369.     m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
  370.     m_pSourceElement->m_ulAuthoredClipBegin?
  371.     ulClippedAmt : ulClippedAmt +
  372.     m_pSourceElement->m_ulAuthoredClipBegin);
  373.     if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
  374.     {
  375. if (m_pSourceElement->m_ulDuration > ulClippedAmt)
  376. {
  377.     m_pSourceElement->m_ulDuration -= ulClippedAmt;
  378. }
  379. // /else duration is negative; it can't ever play.
  380. else
  381. {
  382.     m_pSourceElement->m_ulDuration = 0;
  383. }
  384.     }
  385. }
  386.     }
  387.     // /Fixes most of PR64499: when restarting the parent of a
  388.     // long-sync-arc-begun element, the begin should still be based on
  389.     // the long sync-arc's global time:
  390.     else if ((UINT32)-1 != m_pSourceElement->m_ulLongSyncArcBeginInGroupTime
  391.     &&  m_pSourceElement->m_bIsRestarting)
  392.     {
  393. SMILNode* pSyncNode = !m_pParser? NULL :
  394.        m_pParser->getSyncAncestor(m_pSourceElement->m_pNode);
  395. HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
  396. if (pSyncNode  &&  pSyncNode->m_pElement->m_bIsRestarting)
  397. {
  398.     m_pSourceElement->m_ulDelay =
  399.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime;
  400. }
  401.     }
  402.     // /Else we've established that the beginOffset is not set, so
  403.     // just use the delay:
  404.     else
  405.     {
  406. m_pSourceElement->m_ulDelay = ulDelay;
  407. // /Fixes PR 71386 and PR 77406: event-based begins with sync-
  408. // arc ends (that are already resolved, here) should not
  409. // include the delay twice; use the *end* not the *duration*:
  410. if (m_pSourceElement->m_bEndOffsetSet  &&
  411. // /Fixes PR 8XYXZ (broken by original PR 71386 fix);
  412. // If being set by parent, we don't need to do anything
  413. // because delay is parent delay, not explicitly-set
  414. // begin val:
  415. !bSetByParent)
  416. {
  417.     // /If dur was explicitly authored along with end, use the
  418.     // min(end, dur+delay):
  419.     if (WAY_IN_THE_FUTURE ==
  420.     m_pSourceElement->m_ulAuthoredDur  ||
  421.     (UINT32)-1 == m_pSourceElement->m_ulAuthoredDur  ||
  422.     // /Fixes PR 71386 Part 3 = version where element
  423.     // has end="x.end" AND has dur="z"; if z+delay >
  424.     // x.end, ignore dur:
  425.     (m_pSourceElement->m_ulAuthoredDur +
  426.     m_pSourceElement->m_ulDelay >
  427.     m_pSourceElement->m_lEndOffset))
  428.     {
  429. if (m_pSourceElement->m_lEndOffset > 0  &&
  430. (ULONG32)m_pSourceElement->m_lEndOffset >=
  431. m_pSourceElement->m_ulDelay)
  432. {
  433.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  434.     FALSE;
  435.     m_pSourceElement->m_ulDuration =
  436.     m_pSourceElement->m_lEndOffset -
  437.     m_pSourceElement->m_ulDelay;
  438. }
  439. else
  440. {
  441.     HX_ASSERT(0  &&  "pleaseContact_ehodge!");
  442.     m_pSourceElement->m_ulDuration = 0;
  443. }
  444.     }
  445. }
  446.     }
  447.     m_bDelaySet = TRUE;
  448.     if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
  449.     {
  450. m_pParser->insertTimelineElement(m_pID, 
  451.     m_pSourceElement->m_ulDelay);
  452.     }
  453.             // XXXMEH - animation can be children of media elements, so when
  454.             // a media element gets its delay set, then we need to
  455.             // set the delay of any children
  456.     if(m_pChildren)
  457.     {
  458.                 LISTPOSITION pos = m_pChildren->GetHeadPosition();
  459.                 while (pos)
  460.                 {
  461.                     CSmilTimelineElement* pChildElement =
  462.                         (CSmilTimelineElement*) m_pChildren->GetNext(pos);
  463.                     if (pChildElement)
  464.                     {
  465.                         pChildElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  466.                     }
  467.                 }
  468.     }
  469. }
  470.     }
  471.     else
  472.     {
  473. HX_ASSERT(WAY_IN_THE_FUTURE > ulDelay); // /PR 59584-related check.
  474. if(m_pSourceElement->m_bBeginOffsetSet)
  475. {
  476.     m_pSourceElement->m_ulDelay = (
  477. ((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
  478. (UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
  479. }
  480. else
  481. {
  482.     // /There are two cases where we might arrive here with
  483.     // ulDelay not equalling ulPreviouslySetDelay; one is when the
  484.     // original delay is based on a sync-arc to an element that never
  485.     // gets added to the timeline, and the other is when the original
  486.     // delay is based on a long sync-arc.  The following allows both
  487.     // to work; we don't want to use the new delay if the orig one
  488.     // was greater than the new one, otherwise we'll play it too soon
  489.     // and that happens in SMIL2 Timing interop case 1.15:
  490.     if (!bSetByParent  ||  ulDelay > ulPreviouslySetDelay)
  491.     {
  492. m_pSourceElement->m_ulDelay = ulDelay;
  493.     }
  494. }
  495. // /If we've got a long sync-arc begin delay that is earlier (and
  496. // also resolved earlier) than our parent's begin delay, then we want
  497. // to do a clip-begin of the difference, e.g,:
  498. //   <par begin="3s">
  499. //     <video begin="someElementBeginningAtTimeZero.begin" .../> ...
  500. // so the video element should begin at 3s and clip the 1st 3s of it.
  501. if (bSetByParent  &&
  502. ulPreviouslySetDelay < m_pSourceElement->m_ulDelay)
  503. {
  504.     LONG32 lDiff = m_pSourceElement->m_ulDelay -ulPreviouslySetDelay;
  505.     HX_ASSERT(lDiff >= 0);
  506.     ULONG32 ulDiff = (ULONG32)lDiff;
  507.     // /If clip-begin is invalid, set it otherwise add to it:
  508.     m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
  509.     m_pSourceElement->m_ulAuthoredClipBegin?
  510.     ulDiff : ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
  511.     if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
  512.     {
  513. if (m_pSourceElement->m_ulDuration > ulDiff)
  514. {
  515.     m_pSourceElement->m_ulDuration -= ulDiff;
  516. }
  517. else
  518. {
  519.     m_pSourceElement->m_ulDuration = 0;
  520. }
  521. if (m_pSourceElement->m_pNode)
  522. {
  523.     m_pParser->resetTimelineElementDuration(
  524.     (const char*)m_pSourceElement->m_pNode->m_id,
  525.     m_pSourceElement->getPureDuration(),
  526.     ulPreviouslySetPureDuration);
  527.     m_pParser->m_pTimelineElementManager->notify(
  528.     (const char*)m_pSourceElement->m_pNode->m_id);
  529. }
  530.     }
  531. }
  532. // /More for PR 50411: if it wasn't inserted yet, do so:
  533. // /(Also helps fix other long-sync-arc bugs like PR 64498 & PR 64499):
  534. if (m_pSourceElement->m_bAwaitingSyncAncestorBeginNotification)
  535. {
  536.     HX_ASSERT(!m_pSourceElement->m_bInsertedIntoTimeline);
  537.     m_pParser->insertTimelineElement(m_pID,
  538.     m_pSourceElement->m_ulDelay);
  539.     m_pSourceElement->m_bAwaitingSyncAncestorBeginNotification =
  540.     FALSE;
  541. }
  542.     }
  543.     // /This helps fix PR 50588 (and other sync-arc-to-x's-begin-where-x-has-
  544.     // resolved-delay-but-not-resolved-duration bugs); notify sync-arc
  545.     // dependents if our delay (or duration) was set or changed:
  546.     if (ulPreviouslySetDelay != m_pSourceElement->m_ulDelay  ||
  547.     ulPreviouslySetPureDuration != m_pSourceElement->getPureDuration())
  548.     {
  549. m_pParser->m_pTimelineElementManager->notify(m_pID);
  550.     }
  551. }
  552. void 
  553. CSmilTimelineElement::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
  554.   BOOL bDurationExtendingDueToPause)
  555. {
  556. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  557.     {
  558. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  559. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  560. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  561. ::fprintf(f1, "CSmilTimelineElement{%s}::setDuration(ulDuration=%lu, "
  562. "bSetFromParent=%sE) m_pSourceElement->m_ulDelay=%lu, m_bDelaySet=%sn",
  563. (const char*)m_pID, ulDuration,
  564. bSetFromParent?"TRU":"FALS", m_pSourceElement->m_ulDelay,
  565. m_bDelaySet?"TRUE":"FALSE-#############!!! DUDE!");
  566. ::fclose(f1);
  567. bFirstTimeAddDurDebugout = FALSE;
  568.     }
  569. #endif
  570.     BOOL bTrackStartsTooLateSoTrackRemoved = FALSE;
  571.     ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  572.     if(bSetFromParent)
  573.     {
  574. BOOL bOKToOverrideDuration = FALSE;
  575. if ((UINT32)-1 == m_pSourceElement->m_ulAuthoredDur)
  576. {
  577.     if (!m_pSourceElement->m_bHasExplicitEnd  ||  !m_bDurationSet)
  578.     {
  579. bOKToOverrideDuration = TRUE;
  580.     }
  581. }
  582. else if (m_pSourceElement->m_ulAuthoredDur == WAY_IN_THE_FUTURE  &&
  583. m_pSourceElement->m_bHasExplicitEnd  &&  m_bDurationSet  &&
  584. // /Fixes PR 50676 part 5: if m_bDurationSet but duration was
  585. // not set to anything but unresolved, then we do want to
  586. // override the unresolved value; this continues to let the
  587. // fix work from 5/9/2001's addition of this else-if:
  588. m_pSourceElement->m_ulDuration != WAY_IN_THE_FUTURE)
  589. {
  590.     bOKToOverrideDuration = FALSE;
  591. }
  592. else if (m_pSourceElement->m_ulAuthoredDur >= ulDuration  &&
  593.     ((UINT32)-1 == m_pSourceElement->m_ulMaxActiveDur  ||
  594.     m_pSourceElement->m_ulMaxActiveDur >= ulDuration) )
  595. {
  596.     // /XXXEH- I need to find content that has this feature;
  597.     // I'm pretty sure I want to add m_ulBeginOffsetFromSyncBase to
  598.     // m_ulAuthoredDur when comparing with ulDuration, above, since
  599.     // ulDuration is in syncbase time coordinate system:
  600.     HX_ASSERT((!m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  ||
  601.     (m_pSourceElement->m_ulBeginOffsetFromSyncBase +
  602.     m_pSourceElement->m_ulAuthoredDur >= ulDuration) )  &&
  603.     "contact ehodge to fix");
  604.     bOKToOverrideDuration = TRUE;
  605. }
  606. // /If begin="5s" and end|dur|max are explicitly set, don't override
  607. // the duration (interop #1.1: BeginEndEvents_Case1.smi):
  608. // /XXXEH- make sure delay is accounted for (if "ulDuration" is
  609. // really delay+dur):
  610. if (bOKToOverrideDuration)
  611. {
  612.     // /Fixes BUG-20001116_parDurExtended_due_to_syncArc_delay.smi:
  613.     ULONG32 ulRevisedDur = ulDuration;
  614.     BOOL bOkToSetDuration = TRUE;
  615.     BOOL bOKToResetDurationIncludesDelayVar = TRUE;
  616.     BOOL bRevisedDurDoesNotIncludeDelayBeyondSyncbase = FALSE;
  617.     // /Note: when we say "parent" in this function, we really
  618.     // mean sync ancestor (e.g., par when switch is our parent and
  619.     // par is parent of switch).
  620.     ULONG32 ulSyncBaseDelay = (UINT32)-1;
  621.     SMILNode* pSyncNode = !m_pParser? NULL :
  622.    m_pParser->getSyncAncestor(m_pSourceElement->m_pNode);
  623.     HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
  624.     if (pSyncNode  &&  pSyncNode->m_pElement)
  625.     {
  626. ulSyncBaseDelay = pSyncNode->m_pElement->m_ulDelay;
  627. // /XXXEH- in PR 59584 (which works OK with code as-is),
  628. // syncNode is a Seq but prior sibling should really be
  629. // treated as the "sync base", not the seq.  There are 3
  630. // other places in this file where this code is needed,
  631. // but need content that's broken by this before I fix it: PR 6XXX5:
  632. if (pSyncNode->m_tag == SMILSeq)
  633. {
  634.     ulSyncBaseDelay = m_pParser->
  635.     getSyncBaseTimeInGroupTimeCoords(
  636.     m_pSourceElement->m_pNode);
  637. }
  638.     }
  639.     // /We need to make sure that our begin+duration does not exceed
  640.     // our parent's end; the ulDuration begin passed in is our
  641.     // syncBase-imposed duration that already includes our syncBase's
  642.     // delay but does not take into account our begin offset or
  643.     // delay relative to our syncBase's begin.  To adjust for this,
  644.     // set the new duration to ulDuration minus (beginOffset set?
  645.     // beginOffset : (delay-parentDelay):  Note that we can have a
  646.     // delay that is due to a sync-arc and not due to our syncBase's
  647.     // delay and thus we may not have a beginOffset set but we still
  648.     // may begin later than our syncBase:
  649.     if (m_pSourceElement->m_bBeginOffsetSet)
  650.     {
  651. // /Include this code because it fixes
  652. // <par dur="5s" begin="1s"><ref begin="2s"/></par>
  653. // as in BUG-20001116_parDurExtended_due_to_syncArc_delay.smi
  654. // (which broke again due to fix for PR 53514, below, I think):
  655. if (m_pSourceElement->m_lBeginOffset > 0)
  656. {
  657.     ulRevisedDur=((ULONG32)m_pSourceElement->m_lBeginOffset>=
  658.     ulRevisedDur)? 0 : (ulRevisedDur -
  659.     (ULONG32)m_pSourceElement->m_lBeginOffset);
  660.     bRevisedDurDoesNotIncludeDelayBeyondSyncbase = TRUE;
  661.     // /Fixes PR 58568: if revised dur is 0 or negative
  662.     // (ULONG32 floor of 0 prevents it from being negative),
  663.     // then we need to remove the track if it's been added
  664.     // already, otherwise it'll play in spite of it's
  665.     // parent ending before that time:
  666.     if (0 == ulRevisedDur)
  667.     {
  668. if (m_pSourceElement->m_pHandler  &&
  669. m_pSourceElement->m_bInsertedIntoTimeline)
  670. {
  671.     // /The following signals subsequent timeline
  672.     // adjustments to ignore this element in parent
  673.     // duration computations:
  674.     m_pSourceElement->m_bCurEndClippedByParent = TRUE;
  675.     HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  676.     handleTrackRemoval((const char*)m_pID,
  677.     (INT32)m_pSourceElement->m_pNode->m_nGroup);
  678.     if (HXR_OK == retval2)
  679.     {
  680. // /XXXEH- verify in SMIL 2.0 spec how to
  681. // handle syncArcs to element that's beyond
  682. // its syncBase and thus won't start:
  683. // /Fixes case where element has sync arc
  684. // to this end time and we need to notify it
  685. // that we've ended early:
  686. m_pParser->m_pTimelineElementManager->notify((const char*)m_pID);
  687. bTrackStartsTooLateSoTrackRemoved = TRUE;
  688. goto cleanup;
  689.     }
  690. }
  691.     }
  692. }
  693.     }
  694.     else // /No begin offset, so use delay minus syncBase delay:
  695.     {
  696. if (pSyncNode  &&  pSyncNode->m_pElement)
  697. {
  698.     if ((UINT32)-1 != ulSyncBaseDelay  &&
  699.     (UINT32)-1 != m_pSourceElement->m_ulDelay )
  700.     {
  701. HX_ASSERT(m_pSourceElement->m_ulDelay >=
  702. ulSyncBaseDelay);
  703. if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay  ||
  704. // /Helps fix PR 66391: if delays are equal &
  705. // revisedDur=0, then remove this track:
  706. (0 == ulRevisedDur  &&
  707. m_pSourceElement->m_ulDelay == ulSyncBaseDelay))
  708. {
  709.     ULONG32 ulEffectiveBeginOffset =
  710.     m_pSourceElement->m_ulDelay -
  711.     ulSyncBaseDelay;
  712.     ulRevisedDur =
  713.     ulRevisedDur>ulEffectiveBeginOffset?
  714.     ulRevisedDur-ulEffectiveBeginOffset : 0;
  715.     bRevisedDurDoesNotIncludeDelayBeyondSyncbase = TRUE;
  716.     bOKToResetDurationIncludesDelayVar = FALSE;
  717.     // /Be sure to update the begin offset relative
  718.     // to the parent:  Helps fix
  719.     // "...20001116_parDurExtended_due_to_syncArc..."
  720.     m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase =
  721.     TRUE;
  722.     m_pSourceElement->m_ulBeginOffsetFromSyncBase =
  723.     ulEffectiveBeginOffset;
  724.     // /Fixes part of PR 50684: if revised dur is 0
  725.     // or negative (ULONG32 floor of 0 prevents it
  726.     // from being negative), then we need to remove
  727.     // the track if it's been added already:
  728.     if (0 == ulRevisedDur  &&
  729.     m_pSourceElement->m_pHandler  &&
  730.     m_pSourceElement->m_bInsertedIntoTimeline)
  731.     {
  732. m_pSourceElement->m_bCurEndClippedByParent = TRUE;
  733. HX_RESULT retval2 = m_pSourceElement->m_pHandler->
  734. handleTrackRemoval((const char*)m_pID,
  735. (INT32)m_pSourceElement->m_pNode->m_nGroup);
  736. if (HXR_OK == retval2)
  737. {
  738.     // /Fixes case where element has sync arc
  739.     // to this end time and we need to notify it
  740.     // that we've ended early:
  741.     m_pParser->m_pTimelineElementManager->notify((const char*)m_pID);
  742.     bTrackStartsTooLateSoTrackRemoved = TRUE;
  743.     goto cleanup;
  744. }
  745.     }
  746. }
  747.     }
  748.     else if ((UINT32)-1 == ulSyncBaseDelay)
  749.     {
  750. // /Fixes case where par parent child of excl was
  751. // allowing child to begin even though par has no
  752. // explicit resolved begin and thus shouldn't begin:
  753. bOkToSetDuration = FALSE;
  754.     }
  755. }
  756.     }
  757.     if (bOkToSetDuration  &&  ((UINT32)-1 ==
  758.     m_pSourceElement->m_ulDuration  ||
  759.     m_pSourceElement->m_ulDuration < ulRevisedDur) )
  760.     {
  761. HX_ASSERT(m_pSourceElement->m_ulDuration == m_pSourceElement->getPureDuration());
  762. // /Adding this if() fixes PR 53514; parent explicit dur was
  763. // being forced on this child even if child has a shorter
  764. // intrinsic duration (which isn't known yet).  We need to
  765. // hold off setting the duration and rather set the max
  766. // duration:
  767. setMaxDuration(ulRevisedDur);
  768.     }
  769.     else if (bOkToSetDuration)
  770.     {
  771. m_bDurationSet = m_bDontResetDuration = TRUE;
  772. if (m_pSourceElement->m_ulDuration != ulRevisedDur)
  773. {
  774.     // /Parent-imposed duration always is relative to parent
  775.     // begin, so duration thus includes delay offset from
  776.     // parent.  Don't set flag unless offset>0, for
  777.     // consistency:
  778.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  779.     m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
  780.     {
  781. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
  782.     }
  783.     if (bRevisedDurDoesNotIncludeDelayBeyondSyncbase)
  784.     {
  785. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = FALSE;
  786.     }
  787.     // /Adding this if() conditional around the call to
  788.     // "resetTimelineElement...()" makes PR55885 happen only
  789.     // after the first time it's played.  If you don't close
  790.     // the player and then restart the clip, sometimes 55885
  791.     // bug still appears; need to debug with core folks to
  792.     // see why this happens.
  793.     // /NOTE: Adding the following conditional *does* 100% fix
  794.     // "BUG-20010613-clickAllFourAndRestartOfGreenCauses..."
  795.     // "...ExtensionOfTimelinePastParEnd.smil":
  796.     if ((UINT32)-1 != m_pSourceElement->m_ulDelay)
  797.     {
  798. m_pParser->resetTimelineElementDuration(m_pID,
  799. // /Using the revised dur here helps fix
  800. // PR 59223, PR 50684, & PR 56795 (and
  801. // probably a lot of others):
  802. ulRevisedDur, ulPriorPureDuration);
  803.     }
  804. }
  805.     }
  806. }
  807. // /Fixes bug where par with a synchbase end (e.g., end="foo.begin")
  808. // was being ignored completely because its children were never
  809. // being added to the timeline:
  810. if (!m_pSourceElement->m_bInsertedIntoTimeline)
  811. {
  812.     if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
  813.     {
  814. // /Helps fix timing interop cases in the 11.2-11.9 range:
  815. if ((UINT32)-1 != m_pSourceElement->m_ulDelay)
  816. {
  817.     m_pParser->insertTimelineElement(m_pID, 
  818.     m_pSourceElement->m_ulDelay);
  819. }
  820.     }
  821. }
  822.     }
  823.     else // /Else this duration is not being set by parent:
  824.     {
  825. if(!m_bDurationSet  ||
  826. // /Helps fix PR 86107; if pause is extending duration, we're
  827. // only here to notify our dependents and ancestor excl so it
  828. // can potentially update its duration so subSEQuent clips can
  829. // adjust their delays outward before getting scheduled w/core:
  830. bDurationExtendingDueToPause)
  831. {
  832.     LONG32 lDelayFromParentBegin = 0;
  833.     HX_ASSERT((!m_pSourceElement->m_bBeginOffsetSet  ||
  834.     m_pSourceElement->m_lBeginOffset>=0  ||
  835.     m_pSourceElement->m_bNegBeginOffsetAlreadyUsed)  &&
  836.     "ehodge_please_help_me_find_content_that_trips_this");
  837.     if (m_pSourceElement->m_bBeginOffsetSet  &&
  838.     // /Don't adjust if already adjusted for neg offset:
  839.     !m_pSourceElement->m_bNegBeginOffsetAlreadyUsed)
  840.     {
  841. lDelayFromParentBegin = m_pSourceElement->m_lBeginOffset;
  842.     }
  843.     // /Handle case where element began based on event or late-
  844.     // resolving time, in which case we want to treat the diff
  845.     // between when it resolved and what its sync-parent begin
  846.     // is as if it were a m_lBeginOffset:
  847.     else if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  848.     {
  849. lDelayFromParentBegin = (LONG32)
  850. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  851.     }
  852.     if (lDelayFromParentBegin>0  &&
  853.     // /1st part of fix for interop case 1.15 where begin and
  854.     // end are explicitly set to same val so dur should be 0:
  855.     ulDuration != 0)
  856.     {
  857. m_pSourceElement->m_ulDuration = (
  858.     ((INT32)ulDuration + lDelayFromParentBegin >0) ?
  859.     (UINT32)(
  860.     (INT32)ulDuration + lDelayFromParentBegin) : 0);
  861. // /NOTE: m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase
  862. // is TRUE in PR 79699 (occasionally) but it plays as expected so
  863. // I removed the HX_ASSERT() on !(..->m_bDurationIncludesDelay...)].
  864. // /XXXEH- 20020625: maybe don't do above adding of delay, and then set this to FALSE?:
  865. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
  866. // /If duration is unresolved or indefinite, don't include
  867. // delay from parent so parent duration doesn't get extended
  868. // beyond WAY_IN_THE_FUTURE:
  869. if (WAY_IN_THE_FUTURE == ulDuration)
  870. {
  871.     m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
  872. }
  873.     }
  874.     else
  875.     {
  876. lDelayFromParentBegin = 0; // /In case it was negative.
  877. m_pSourceElement->m_ulDuration = ulDuration;
  878. // /If end==begin, we need to NOT play the clip but we do
  879. // need to fire a beginEvent and endEvent for it.  However,
  880. // if end < begin, we don't fire these events (as in
  881. // SMIL 2.0 Interop Timing case 1.16):
  882. BOOL bEndBeforeBegin =
  883. m_pSourceElement->m_bBeginOffsetSet  &&
  884. m_pSourceElement->m_bEndOffsetSet  &&
  885. m_pSourceElement->m_lBeginOffset >
  886. m_pSourceElement->m_lEndOffset;
  887. if (0 == m_pSourceElement->m_ulDuration  &&
  888. !bEndBeforeBegin  &&  m_pSourceElement->m_pNode)
  889. {
  890.     // /Raise a beginEvent but don't play the thing (as in
  891.     // SMIL 2.0 Interop Timing case 1.15):
  892.     HX_RESULT rslt = HXR_OK;
  893.     rslt = m_pParser->tryToResolveBeginEndEvents(
  894.     "beginEvent",
  895.     (const char*)m_pSourceElement->m_pNode->m_id,
  896.     m_pSourceElement->m_ulDelay);
  897.     rslt = m_pParser->tryToResolveBeginEndEvents(
  898.     "endEvent",
  899.     (const char*)m_pSourceElement->m_pNode->m_id,
  900.     m_pSourceElement->m_ulDelay);
  901. }
  902.     }
  903.     m_bDurationSet = TRUE;
  904.     HX_ASSERT(m_pSourceElement->m_ulDuration>0  &&
  905.     "timing#1.15: child's dur (=0) not added to parent; refix!");
  906.     if(m_pParent  &&
  907.     // /Timing interop case 1.15 2nd part of fix:
  908.     m_pSourceElement->m_ulDuration>0)
  909.     {
  910. m_pParent->addDuration(m_pSourceElement->m_ulDuration,
  911. m_pSourceElement->m_ulDelay,
  912. (UINT32)lDelayFromParentBegin, m_pID);
  913. m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
  914.     }
  915.     // /Only do this if we're really setting the original duration
  916.     // (and not updating duration due to predicted pause extension):
  917.     if (!bDurationExtendingDueToPause)
  918.     {
  919. // /this keeps track of dur="x" or implicit source dur, in
  920. // case this element restarts after playing at least once:
  921. m_pSourceElement->m_ulOriginalDuration =
  922. m_pSourceElement->getPureDuration();
  923. HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
  924. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
  925.     }
  926. }
  927. else if(!m_bDontResetDuration)
  928. {
  929.     m_pSourceElement->m_ulDuration = ulDuration;
  930.     m_pParser->resetTimelineElementDuration(m_pID,
  931.     m_pSourceElement->getPureDuration(),
  932.     ulPriorPureDuration);
  933.     // /this keeps track of dur="x" or implicit source dur, in
  934.     // case this element restarts after playing at least once:
  935.     m_pSourceElement->m_ulOriginalDuration =
  936.     m_pSourceElement->getPureDuration();
  937.     HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
  938.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
  939. }
  940. // /Adding the following else-if fixes PR 52110: if parent explicit
  941. // dur sets this's duration but this never got added to parent (via
  942. // addDuration()), then all subSEQuent tracks won't ever get resolved
  943. // begins:
  944. else if(!m_pSourceElement->m_bAddDurationAlreadyDone)
  945. {
  946.     HX_ASSERT(m_bDurationSet); // /Here because this was already set.
  947.     HX_ASSERT(m_bDelaySet  &&  (UINT32)-1 != m_pSourceElement->m_ulDelay);
  948.     HX_ASSERT(m_pSourceElement->m_ulDuration>0  &&
  949.     "child's dur (=0) not added to parent; refix!");
  950.     if(m_pParent  &&  m_pSourceElement->m_ulDuration>0)
  951.     {
  952. ULONG32 ulDelayFromSyncBaseBegin = 0;
  953. if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  954. {
  955.     ulDelayFromSyncBaseBegin =
  956.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  957. }
  958. m_pParent->addDuration(m_pSourceElement->m_ulDuration, 
  959. m_pSourceElement->m_ulDelay,
  960. ulDelayFromSyncBaseBegin, m_pID);
  961. m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
  962.     }
  963. }
  964. // /If "dur" attribute value or intrinsic dur is less than the
  965. // min attribute value or greater than the max attribute value,
  966. // then we need to use min or max attribute's value as the duration:
  967. if (!m_bDontResetDuration  &&
  968. (m_pSourceElement->m_bUseMediaDurForMinDur  ||
  969. m_pSourceElement->m_bUseMediaDurForMaxDur  ||
  970. m_pSourceElement->m_ulMinActiveDur > 0  ||
  971. m_pSourceElement->m_ulMaxActiveDur != ((UINT32)-1) ) )
  972. {
  973.     BOOL bDoUpdate = FALSE;
  974.     LONG32 lBeginOffset = 0;
  975.     if (m_pSourceElement->m_bBeginOffsetSet)
  976.     {
  977. lBeginOffset = m_pSourceElement->m_lBeginOffset;
  978.     }
  979.     // /First, check if m_pSourceElement->m_bUseMediaDurForMinDur
  980.     // is TRUE.  If so, we want to use the max of ulDuration
  981.     // (media's intrinsic dur) and any explicitly-set dur (via
  982.     // dur="..." {or end="..."[-begin=".."]}:
  983.     if (m_pSourceElement->m_bUseMediaDurForMinDur)
  984.     {
  985. if (((UINT32)-1) != m_pSourceElement->m_ulAuthoredDur)
  986. {
  987.     HX_ASSERT(0 == m_pSourceElement->m_ulMinActiveDur);
  988.     // /Use authored dur if it's greater than intrinsic
  989.     // duration OR if max<min (since max<min negates both
  990.     // properties):
  991.     if (m_pSourceElement->m_ulAuthoredDur > ulDuration  ||
  992.     (((UINT32)-1) !=
  993.     m_pSourceElement->m_ulMaxActiveDur  &&
  994.     m_pSourceElement->m_ulMaxActiveDur < ulDuration))
  995.     {
  996. m_pSourceElement->m_ulDuration =
  997. m_pSourceElement->m_ulAuthoredDur;
  998. bDoUpdate = TRUE;
  999.     }
  1000. }
  1001.     }
  1002.     // /Next, check if m_pSourceElement->m_bUseMediaDurForMaxDur
  1003.     // is TRUE.  If so, we want to use the min of ulDuration
  1004.     // (media's intrinsic dur) and any explicitly-set dur (via
  1005.     // dur="..." or {end="..."[-begin=".."]}:
  1006.     else if (m_pSourceElement->m_bUseMediaDurForMaxDur)
  1007.     {
  1008. if (((UINT32)-1) != m_pSourceElement->m_ulAuthoredDur)
  1009. {
  1010.     HX_ASSERT(((UINT32)-1) ==
  1011.     m_pSourceElement->m_ulMaxActiveDur);
  1012.     // /Use authored dur if it's less than intrinsic
  1013.     // duration OR if min>max (since min>max negates both
  1014.     // properties):
  1015.     if (m_pSourceElement->m_ulAuthoredDur < ulDuration  ||
  1016.     (0 != m_pSourceElement->m_ulMinActiveDur  &&
  1017.     m_pSourceElement->m_ulMinActiveDur > ulDuration))
  1018.     {
  1019. m_pSourceElement->m_ulDuration =
  1020. m_pSourceElement->m_ulAuthoredDur;
  1021. bDoUpdate = TRUE;
  1022.     }
  1023. }
  1024.     }
  1025.     // /If no "dur" or "end" was specified, use the greater of the
  1026.     // media's intrinsic dur and its min without exceeding its max,
  1027.     // if any:
  1028.     else if(((UINT32)-1) == m_pSourceElement->m_ulAuthoredDur)
  1029.     {
  1030. if (m_pSourceElement->m_ulMinActiveDur!=0  &&
  1031. m_pSourceElement->m_ulDuration <
  1032. m_pSourceElement->m_ulMinActiveDur)
  1033. {
  1034.     m_pSourceElement->m_ulDuration =
  1035.     m_pSourceElement->m_ulMinActiveDur;
  1036.     bDoUpdate = TRUE;
  1037. }
  1038. if (((UINT32)-1) != m_pSourceElement->m_ulMaxActiveDur  &&
  1039. m_pSourceElement->m_ulDuration >
  1040. m_pSourceElement->m_ulMaxActiveDur)
  1041. {
  1042.     m_pSourceElement->m_ulDuration =
  1043.     m_pSourceElement->m_ulMaxActiveDur;
  1044.     bDoUpdate = TRUE;
  1045. }
  1046.     }
  1047.     // /If the duration is less than the specified min, use
  1048.     // the min (and we already know that the min < max, so we don't
  1049.     // need to look at the max, if any):
  1050.     else if (m_pSourceElement->m_ulDuration <
  1051. m_pSourceElement->m_ulMinActiveDur)
  1052.     {
  1053. m_pSourceElement->m_ulDuration =
  1054. m_pSourceElement->m_ulMinActiveDur;
  1055. bDoUpdate = TRUE;
  1056.     }
  1057.     // /If the duration authored is greater than the specified max,
  1058.     // use the max (and we already know that the min < max, so we
  1059.     // don't need to look at the min, if any):
  1060.     else if (m_pSourceElement->m_ulDuration >
  1061. m_pSourceElement->m_ulMaxActiveDur)
  1062.     {
  1063. m_pSourceElement->m_ulDuration =
  1064. m_pSourceElement->m_ulMaxActiveDur;
  1065. bDoUpdate = TRUE;
  1066.     }
  1067.     else // /use authored duration:
  1068.     {
  1069. m_pSourceElement->m_ulDuration =
  1070. m_pSourceElement->m_ulAuthoredDur;
  1071. bDoUpdate = TRUE;
  1072.     }
  1073.     if (bDoUpdate)
  1074.     {
  1075. LONG32 lDiff =
  1076. (LONG32)m_pSourceElement->m_ulDuration +
  1077. lBeginOffset;
  1078. m_pSourceElement->m_ulDuration = lDiff>0?
  1079. lDiff : 0;
  1080. m_pParser->resetTimelineElementDuration(m_pID,
  1081. m_pSourceElement->getPureDuration(),
  1082. ulPriorPureDuration);
  1083. // /This keeps track of first-play dur, in case this
  1084. // element restarts during or after playing at least
  1085. // once:
  1086. m_pSourceElement->m_ulOriginalDuration =
  1087. m_pSourceElement->getPureDuration();
  1088. HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
  1089. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
  1090.     }
  1091. }
  1092.     }
  1093. cleanup:
  1094.     if (m_pDependent  &&  ((UINT32)-1 != m_pSourceElement->m_ulDelay))
  1095.     {
  1096. HX_ASSERT(WAY_IN_THE_FUTURE >= m_pSourceElement->m_ulDuration +
  1097.         m_pSourceElement->m_ulDelay); // 59584(media version) & 50848 
  1098.     }
  1099.     if(m_pDependent  &&
  1100.     // /Helps fix PR 66391: If we removed this track because it fell
  1101.     // completely outside its parent's time bounds, then we shouldn't
  1102.     // update our dependent, but rather allow further processing of the
  1103.     // parent seq's setDuration() to remove it's track:
  1104.     !bTrackStartsTooLateSoTrackRemoved  &&
  1105.     // /Helps fix some timing interop cases in the 11.2-11.9 range:
  1106.     ((UINT32)-1 != m_pSourceElement->m_ulDelay)  &&
  1107.     // /Helps fix case where as-yet-unresolved end of seq child should
  1108.     // *not* be used to resolve next sibling's begin: (PR 50848)
  1109.     WAY_IN_THE_FUTURE > m_pSourceElement->m_ulDuration +
  1110.     m_pSourceElement->m_ulDelay) // /+delay for PR 59584-related bug.
  1111.     {
  1112. //Removed the addition of m_pSourceElement->m_ulDelay from the
  1113. // source's duration because the source's duration already includes
  1114. // its delay; we don't want to count the delay twice. Fixes PR 13983:
  1115. // /*XXXEH- UNFIXES 13983 by adding back in the ...m_ulDelay addition;
  1116. // the full fix for 13983 requires keeping track of begin=... delay
  1117. // (as opposed to seq-related delay) and then subtracting that begin
  1118. // delay from the m_ulDelay below:
  1119. adjustDependentDuration(m_pDependent);
  1120. // /XXXEH- TODO: figure out if we need to claim this is being set by
  1121. // "parent" (which is really time base) so clip-begin-like action can
  1122. // occur; I don't think so, however:
  1123. // /XXXEH- I think this fixes PR 13983 without breaking other stuff,
  1124. // but need to make sure:
  1125. // /Don't propagate delay of sourceElement (PR 13983) in case its
  1126. // duration already includes its begin offset:
  1127. ULONG32 ulDelayOfSourceElem = m_pSourceElement->m_ulDelay +
  1128. m_pSourceElement->m_ulDuration;
  1129. if (m_pSourceElement->m_bBeginOffsetSet  &&
  1130. m_pSourceElement->m_lBeginOffset > 0)
  1131. {
  1132.     ulDelayOfSourceElem =
  1133.     ((INT32)ulDelayOfSourceElem >
  1134.     m_pSourceElement->m_lBeginOffset ?
  1135.     ulDelayOfSourceElem - m_pSourceElement->m_lBeginOffset :
  1136.     0);
  1137. #if defined(XXXEH_DEBUG)
  1138.     HX_ASSERT(!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
  1139.     "ehodge: don't count delay twice!");
  1140. #endif
  1141.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1142.     {
  1143. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <=
  1144. m_pSourceElement->m_lBeginOffset); // /PR 6XXXX.
  1145.     }
  1146. }
  1147. // /If this is a repeat element and the first iteration element
  1148. // was clipped due to a negative begin offset, we want to use the
  1149. // full duration for this clip:
  1150. if (m_pDependent->m_pSourceElement->m_pNode->m_repeatTag ==
  1151. RepeatReplica  &&  m_pSourceElement->m_lBeginOffset < 0)
  1152. {
  1153.     ULONG32 ulRepeatIterationFullDur =
  1154.     m_pSourceElement->m_ulOriginalDuration -
  1155.     m_pSourceElement->m_lBeginOffset;
  1156.     if ((UINT32)-1 != m_pSourceElement->m_ulOriginalDuration)
  1157.     {
  1158. m_pDependent->m_pSourceElement->m_ulDuration =
  1159. ulRepeatIterationFullDur;
  1160.     }
  1161. }
  1162. if (WAY_IN_THE_FUTURE < ulDelayOfSourceElem)
  1163. {
  1164.     HX_ASSERT(WAY_IN_THE_FUTURE == ulDelayOfSourceElem  &&  "PR 59584");
  1165.     ulDelayOfSourceElem = WAY_IN_THE_FUTURE; // /For PR 59584.
  1166. }
  1167. m_pDependent->setDelay(ulDelayOfSourceElem, FALSE);
  1168.     }
  1169.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1170. }
  1171. void
  1172. CSmilTimelineElement::setMaxDuration(UINT32 ulMaxDuration)
  1173. {
  1174.     m_bMaxDurationSet = TRUE;
  1175.     m_pSourceElement->m_ulMaxDuration = ulMaxDuration;
  1176. }
  1177. void 
  1178. CSmilTimelineElement::adjustDependentDuration(CSmilTimelineElement* pDependent)
  1179. {
  1180.     if (m_pParent)
  1181.     {
  1182. m_pParent->adjustDependentDuration(m_pDependent);
  1183.     }
  1184. }
  1185. void 
  1186. CSmilTimelineElement::resetDelay(UINT32 ulDelay)
  1187. {
  1188.     INT32   lAdjustedDelay = 0;
  1189.     UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;
  1190.     if(m_pSourceElement->m_bBeginOffsetSet)
  1191.     {
  1192. lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
  1193. m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
  1194.     }
  1195.     else
  1196.     {
  1197. m_pSourceElement->m_ulDelay = ulDelay;
  1198.     }
  1199.     
  1200.     if (m_pDependent && m_bDurationSet)
  1201.     {
  1202. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1203. ULONG32 ulTotalDelay = 0;
  1204.         if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1205. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1206. {
  1207.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1208. }
  1209. if (HXR_OK !=
  1210. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1211. {
  1212.     goto doneSettingDependent;
  1213. }
  1214. #else
  1215. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1216. m_pSourceElement->m_ulDuration;
  1217. // /Helps fix PR 6XXXX(media version): if delay is already packed
  1218. // into the duration, then don't count it twice (as can happen in
  1219. // <seq><ref begin="1s" .../><ref begin="1s" .../>...):
  1220. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1221. {
  1222.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1223. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
  1224.     {
  1225. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1226. ulTotalDelay);
  1227. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1228. ulTotalDelay)
  1229. {
  1230.     ulTotalDelay -=
  1231.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1232. }
  1233.     }
  1234. }
  1235. #endif
  1236. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1237. {
  1238.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1239.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1240. }
  1241.  
  1242. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  1243.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  1244.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  1245.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  1246.     ::fprintf(f1, "nt%s:CSmilTimelineElement::resetDelay(%lu):from %lu to %lu;" 
  1247.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID, 
  1248.     ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay, 
  1249.     (const char*)m_pDependent->m_pID, ulTotalDelay); 
  1250.     ::fclose(f1); 
  1251.     bFirstTimeAddDurDebugout = FALSE; 
  1252. #endif
  1253.  
  1254. m_pDependent->resetDelay(ulTotalDelay);
  1255.     }
  1256. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1257. doneSettingDependent:
  1258. #endif
  1259.     if (m_pSourceElement->m_bRendererInitialized)
  1260.     {
  1261. m_pParser->resetTimelineElementDelay(m_pID, m_pSourceElement->m_ulDelay,
  1262. ulPriorDelay);
  1263.     }
  1264.     // /(Added while fixing PR 59851) Let others know our begin time changed:
  1265.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1266. }
  1267. void 
  1268. CSmilTimelineElement::resetDuration(UINT32 ulDuration)
  1269. {
  1270.     INT32 lAdjustedDuration = 0;
  1271.     UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  1272.     
  1273.     if(m_pSourceElement->m_bBeginOffsetSet)
  1274.     {
  1275. if (!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1276. {
  1277.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  1278.     TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
  1279. }
  1280. lAdjustedDuration = (INT32)ulDuration + m_pSourceElement->m_lBeginOffset;
  1281. m_pSourceElement->m_ulDuration = lAdjustedDuration > 0?lAdjustedDuration:0; 
  1282.     }
  1283.     else
  1284.     {
  1285. m_pSourceElement->m_ulDuration = ulDuration;
  1286.     }
  1287.     if(m_pParent)
  1288.     {
  1289. // /Added surrounding if() to prevent adjusting dur of parent when
  1290. // parent has clearly imposed its dur on *this (helps fix PR 58568)
  1291. if (!m_pSourceElement->m_bCurEndClippedByParent)
  1292. {
  1293.     m_pParent->adjustDuration();
  1294. }
  1295.     }
  1296.     if(m_pDependent)
  1297.     {
  1298. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1299. ULONG32 ulTotalDelay = 0;
  1300.         if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  1301. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1302. {
  1303.     HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
  1304. }
  1305. if (HXR_OK !=
  1306. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  1307. {
  1308.     goto doneSettingDependent;
  1309. }
  1310. #else
  1311. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  1312. m_pSourceElement->m_ulDuration;
  1313. // /Helps fix PR 6XXXX(media version): if delay is already packed
  1314. // into the duration, then don't count it twice (as can happen in
  1315. // <seq><ref begin="1s" .../><ref begin="1s" .../>...):
  1316. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  1317. {
  1318.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  1319. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
  1320.     {
  1321. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1322. ulTotalDelay);
  1323. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  1324. ulTotalDelay)
  1325. {
  1326.     ulTotalDelay -=
  1327.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  1328. }
  1329.     }
  1330. }
  1331. #endif
  1332. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  1333. {
  1334.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  1335.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  1336. }
  1337.  
  1338. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  1339.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  1340.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  1341.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  1342.     ::fprintf(f1, "nt%s:CSmilTimelineElement::resetDuration(%lu):from %lu to %lu;"
  1343.     "tresetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  1344.     ulPriorPureDuration, ulDuration, m_pSourceElement->m_ulDuration,
  1345.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  1346.     ::fclose(f1); 
  1347.     bFirstTimeAddDurDebugout = FALSE; 
  1348. #endif 
  1349.  
  1350. // /Helps fix PR 66391; if parent clipped our duration to 0, don't
  1351. // update dependent; that'll be handled in parent seq's setDuration():
  1352. if (0 != ulDuration  &&  !m_pSourceElement->m_bCurEndClippedByParent)
  1353. {
  1354.     m_pDependent->resetDelay(ulTotalDelay);
  1355. }
  1356.     }
  1357. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  1358. doneSettingDependent:
  1359. #endif
  1360.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  1361. }
  1362. void 
  1363. CSmilTimelineElement::adjustDuration()
  1364. {
  1365.     // no-op
  1366.     return;
  1367. }
  1368. HX_RESULT
  1369. CSmilTimelineElement::handlePrefetchFinished(UINT32 ulTimeFinished)
  1370. {
  1371.     HX_RESULT pnr = HXR_FAILED;
  1372.     if ((UINT32)-1 != ulTimeFinished)
  1373.     {
  1374. if (m_pSourceElement  &&  (UINT32)-1==m_pSourceElement->m_ulDuration)
  1375. {
  1376.     if (m_bDelaySet)
  1377.     {
  1378. if (ulTimeFinished > m_pSourceElement->m_ulDelay)
  1379. {
  1380.     ulTimeFinished -= m_pSourceElement->m_ulDelay;
  1381. }
  1382. else
  1383. {
  1384.     ulTimeFinished = 0;
  1385. }
  1386.     }
  1387.     
  1388.     pnr = HXR_OK;
  1389.     setDuration(ulTimeFinished, FALSE);
  1390. }
  1391.     }
  1392.     return pnr;
  1393. }
  1394. void
  1395. // /XXXEH- TODO: [20010411] we need to get more information about *what* just
  1396. // got resolved so we don't re-resolve the m_pSourceElement on something
  1397. // that it already has resolved.  For instance, if the duration of
  1398. // pEventElement changed, we only want to resolve or re-resolve
  1399. // m_pSourceElement's begin and/or end time that are based on the *end* of
  1400. // the event element, and leave be its sync-arcs that are based on the
  1401. // *begin* of the event element.
  1402. // /XXXEH- TODO: [20010411] Don't set m_bBeginOffsetSet and other vars here;
  1403. // wait until the begin|end list is evaluated to get the current
  1404. // instance begin|end time (which may not be the sync arc that gets
  1405. // resolved herein).  Also, do this for par|seq|excl::elementResolved
  1406. CSmilTimelineElement::elementResolved(CSmilTimelineElement* pEventElement)
  1407. {
  1408.     UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
  1409.     BOOL bIsPlayableObjectNotInsertedInTimeline = FALSE;
  1410.     if (!pEventElement->m_pSourceElement  ||
  1411.     (pEventElement->m_pSourceElement->m_pNode  &&
  1412.     (m_pParser->isMediaObject(
  1413.     pEventElement->m_pSourceElement->m_pNode)  ||
  1414.     m_pParser->isNonMediaPlayableObject(
  1415.     pEventElement->m_pSourceElement->m_pNode) )  &&
  1416.     !pEventElement->m_pSourceElement->m_bInsertedIntoTimeline) )
  1417.     {
  1418. bIsPlayableObjectNotInsertedInTimeline = TRUE;
  1419.     }
  1420.     // /Fixes SMIL 2.0 Interop Timing #28.2 (which is PR 52571):
  1421.     // If eventElement can't begin because it begins and ends before its
  1422.     // parent begins, then don't propagate its time to other elements:
  1423.     if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
  1424.     pEventElement->m_pSourceElement->m_lBeginOffset < 0)
  1425.     {
  1426. if (0 == pEventElement->m_pSourceElement->m_ulDuration)
  1427. {
  1428.     return;
  1429. }
  1430.     }
  1431.     BOOL bNeedToResolveBeginTimeListVals = FALSE;
  1432.     BOOL bNeedToResolveEndTimeListVals = FALSE;
  1433.     BOOL bWasInsertedOntoTimeline = FALSE;
  1434.     BOOL bIsInExcl = m_pParser->hasAncestor(SMILExcl,
  1435.     m_pSourceElement->m_pNode);
  1436.     BOOL bPreviousDelaySetVal = m_bDelaySet;
  1437.     BOOL bUseBeginOffsetForPendingBeginList = FALSE;;
  1438.     // /If we are in an excl and we are beginning after our excl parent's
  1439.     // current child-derived end, then go ahead and insert into the timeline,
  1440.     // else see all "We need to go through ..." notes, below.  This fixes
  1441.     // Interop Timing cases #9.35 & 9.36 (that broke while fixing 15.13):
  1442.     // Note that we don't want to insert ANY element that begins after its
  1443.     // parent's immutable end time):
  1444.     BOOL bCantExtendParentDuration = FALSE;
  1445.     ULONG32 ulParentEnd = (UINT32)-1;
  1446.     SMILNode* pSyncBaseNode = m_pParser->getSyncAncestor(
  1447.     m_pSourceElement->m_pNode);
  1448.     LONG32 lSourceElementDelayAdjustmentToSyncBaseTime = 0;
  1449.     if (pSyncBaseNode  &&  pSyncBaseNode->m_pElement)
  1450.     {
  1451. // /XXXEH- TODO: handle case where endsync is SMILEventSourceID and
  1452. // id matches m_pSourceElement->m_pNode->m_id:
  1453. // /XXXEH- TODO: also handle when sync parent has indefinite end|dur:
  1454. if (!pSyncBaseNode->m_pElement->m_bHasExplicitEnd  &&
  1455. !pSyncBaseNode->m_pElement->m_bHasExplicitDur  &&
  1456. (SMILEventSourceFirst !=
  1457. pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag  &&
  1458. SMILEventSourceID !=
  1459. pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag) )
  1460. {
  1461.     bCantExtendParentDuration = FALSE;
  1462.     if ((UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDuration  &&
  1463.     (UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDelay)
  1464.     {
  1465. ulParentEnd = pSyncBaseNode->m_pElement->m_ulDelay +
  1466. pSyncBaseNode->m_pElement->m_ulDuration;
  1467.     }
  1468. }
  1469. else
  1470. {
  1471.     bCantExtendParentDuration = TRUE;
  1472.     if (bIsPlayableObjectNotInsertedInTimeline)
  1473.     {
  1474. // /Fixes BUG-20010423_nothingShouldPlay_beginBasedOn....smi:
  1475. // If eventElement begins after its parent ends, then don't
  1476. // propagate its time to other elements:
  1477. if ((UINT32)-1 == pEventElement->m_pSourceElement->m_ulDelay  ||
  1478. pEventElement->m_pSourceElement->m_ulDelay >=
  1479. pSyncBaseNode->m_pElement->m_ulDelay +
  1480. pSyncBaseNode->m_pElement->m_ulDuration)
  1481. {
  1482.     return; // /Starts too late.
  1483. }
  1484.     }
  1485. }
  1486.     }
  1487.     //First, let's see if we have a begin event to resolve:
  1488.     // /Combining handling of SMILEventSourceBegin and SMILEventSourceClock
  1489.     // fixes SMIL 1.0-syntax PR 112740; the ancient fix for the SMIL2-syntax
  1490.     // version is already in the below code; it's about time we combine
  1491.     // this code, anyway. (SMILEventSourceClock is only used in SMIL 1.0-
  1492.     // syntax syncArcs with clock offsets) :
  1493.     if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
  1494.     m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
  1495.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
  1496.     {
  1497. if(pEventElement->m_bDelaySet)
  1498. {
  1499.     // /Be sure not to overflow using ULONGs since
  1500.     // beginEventClockValue might be negative:
  1501.     LONG32 lDelay =
  1502. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  1503. m_pSourceElement->m_lBeginEventClockValue;
  1504.     // /Fixes SMIL 2.0 Interop Timing #28.1 and others that have
  1505.     // sync-arc to an element with a negative begin time:
  1506.     if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
  1507.     pEventElement->m_pSourceElement->m_lBeginOffset < 0)
  1508.     {
  1509. lDelay += pEventElement->m_pSourceElement->m_lBeginOffset;
  1510.     }
  1511.     // /Fixes PR 82736 (begin=x.being... case) where sync-arc begin
  1512.     // results in negative offset from parent and we've already
  1513.     // adjusted for that:
  1514.     else if (pSyncBaseNode->m_pElement->m_ulDelay > lDelay  &&
  1515.     // /If already inserted, then adjustForNegativeOffset()
  1516.     // won't re-do any adjustment:
  1517.     m_pSourceElement->m_bInsertedIntoTimeline  &&
  1518.     !m_pSourceElement->m_bIsRestarting)
  1519.     {
  1520. // /Don't go earlier than synbase:
  1521. lDelay = pSyncBaseNode->m_pElement->m_ulDelay;
  1522.     }
  1523.     m_bDelaySet = TRUE;
  1524.     m_pSourceElement->m_ulDelay = lDelay<0? 0: (ULONG32)lDelay;
  1525.     if (lDelay < 0)
  1526.     {
  1527. UINT32 ulDiff = (UINT32)(-lDelay);
  1528. // /If clip-begin is invalid, set it otherwise add to orig:
  1529. m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
  1530.         m_pSourceElement->m_ulAuthoredClipBegin? ulDiff :
  1531. ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
  1532. // /logicChange_test.smi: check if -1 before subtracting delay!:
  1533. if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
  1534. {
  1535.     if (m_pSourceElement->m_ulDuration > ulDiff)
  1536.     {
  1537. m_pSourceElement->m_ulDuration -= ulDiff;
  1538.     }
  1539.     // /else duration is negative; it can't ever play.
  1540.     else
  1541.     {
  1542. m_pSourceElement->m_ulDuration = 0;
  1543.     }
  1544. }
  1545.     }
  1546.     // /Now, if our begin delay (not offset) is based on a syncArc,
  1547.     // we need to adjust our dur by the difference between our delay
  1548.     // and our syncBase element's delay:
  1549.     if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
  1550.     m_pSourceElement->m_bEndOffsetSet  &&
  1551.     WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
  1552.     {
  1553. LONG32 lSum = m_pSourceElement->m_lEndOffset;
  1554. // /We need to remove our delay or it will get counted twice
  1555. lSum -= m_pSourceElement->m_ulDelay;
  1556. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  1557. m_pSourceElement->m_ulDuration = (UINT32)(lSum<0 ? 0 : lSum);
  1558. // /Fixes PR 80371: If our duration was set before and is now
  1559. // re-resolving, make sure the following flag is reset to false
  1560. // in case it wasn't before, otherwise show/hide code will
  1561. // subtract the delay from a duration that doesn't include the
  1562. // delay:
  1563. m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = FALSE;
  1564.     }
  1565.     bNeedToResolveBeginTimeListVals = TRUE;
  1566.     if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
  1567.     {
  1568. if (!m_pSourceElement->m_bHasBeenScheduled  ||
  1569. // /Helps fix PR 50588: if restarting, hasBeenSched
  1570. // will still be true, so check if inserted instead:
  1571. (m_pSourceElement->m_bIsRestarting  &&
  1572. !m_pSourceElement->m_bInsertedIntoTimeline) )
  1573. {
  1574.     // /We need to go through the proper channels if we're
  1575.     // in an excl; a priorityClass may prevent us from
  1576.     // starting or may defer our start, so just add us to
  1577.     // the pending begin time list (unless we're extending
  1578.     // the end of our excl parent, as described above):
  1579.     // /First, see if our delay is beyond our parent's end:
  1580.     BOOL bDelayIsBeyondParentEnd = FALSE;
  1581.     if ((UINT32)-1 != ulParentEnd)
  1582.     {
  1583. bDelayIsBeyondParentEnd =
  1584. (m_pSourceElement->m_ulDelay > ulParentEnd);
  1585.     }
  1586.     BOOL bInsertElement = bIsInExcl?
  1587.     (bDelayIsBeyondParentEnd  &&
  1588.     !bCantExtendParentDuration) :
  1589.     ( !(bDelayIsBeyondParentEnd  &&
  1590.     bCantExtendParentDuration) );
  1591.     // /But hold on: if parent's delay isn't yet resolved,
  1592.     // then we can't be inserted until it resolves.  Found
  1593.     // this while fixing long-sync-arc bug PR 64498, par test:
  1594.     // "..._longSyncArcBug-ParWithoutDur...sync.smil":
  1595.     BOOL bParentDelayIsUnresolved = FALSE;
  1596.     if ((UINT32)-1 == pSyncBaseNode->m_pElement->m_ulDelay  ||
  1597.     (pSyncBaseNode->m_pElement->m_pTimelineElement  &&
  1598.     pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelayEvent  &&
  1599.     !pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelaySet ))
  1600.     {
  1601. bInsertElement = FALSE;
  1602. bParentDelayIsUnresolved = TRUE;
  1603.     }
  1604.     if (m_pSourceElement->m_bBeginOffsetSet)
  1605.     {
  1606. // /If it's already been set, then just add this
  1607. // newly-resolved begin time to the pending queue
  1608. // and let it get sorted out there.  This can
  1609. // happen with begin="0s; foo.begin"
  1610. bInsertElement = FALSE;
  1611.     }
  1612.     if (!bInsertElement)
  1613.     {
  1614. // /We need to maintain old "delaySet" value so
  1615. // setDelay() call in eventual call to
  1616. // checkPendingBeginAndEndTimes() can insert this
  1617. // timeline element properly:
  1618. m_bDelaySet = bPreviousDelaySetVal;
  1619. // /Fixes PR 64498: flag the fact that long sync-arc
  1620. // begin is resolving before parent begin is resolved:
  1621. if (bParentDelayIsUnresolved)
  1622. {
  1623.     m_pSourceElement->
  1624. m_bAwaitingSyncAncestorBeginNotification = TRUE;
  1625.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1626.     lDelay;
  1627. }
  1628. // /This else-if is the final fix for PR 64499: if
  1629. // sync-base has multiple begin times, then we also
  1630. // need to prepare for that event restarting it even
  1631. // though its first begin is already resolved:
  1632. else if (pSyncBaseNode->m_pElement->m_pBeginTimeList  &&
  1633. pSyncBaseNode->m_pElement->m_pBeginTimeList->
  1634. GetCount() > 1)
  1635. {
  1636.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1637.     lDelay;
  1638. }
  1639. else
  1640. {
  1641.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1642.     (UINT32)-1;
  1643. }
  1644.     }
  1645.     else
  1646.     {
  1647. bWasInsertedOntoTimeline = TRUE;
  1648. m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1649.     (UINT32)-1;
  1650. m_pParser->insertTimelineElement(m_pID, 
  1651. m_pSourceElement->m_ulDelay);
  1652.     }
  1653. }
  1654.     }
  1655. }
  1656.     }
  1657.     else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
  1658.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID  &&
  1659.     // /Helps fix SMIL 2.0 Interop Timing #28.9 where end as set by parent
  1660.     // was being used when element's end was actually indefinite (or any
  1661.     // value greater than parent's end); that truncated end time should
  1662.     // not propogate; only the pre-truncated time (if any) should be used:
  1663.     (!pEventElement->m_pSourceElement->m_bCurEndClippedByParent) )
  1664.     {
  1665. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  1666. // essentially an unresolved end time, so we should not resolve
  1667. // based on it:
  1668. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  1669. pEventElement->m_pSourceElement->m_ulDuration )
  1670. {
  1671.     ULONG32 ulPriorDelay = m_pSourceElement->m_ulDelay;
  1672.     m_bDelaySet = TRUE;
  1673.     // /Be sure not to overflow using ULONGs since
  1674.     // beginEventClockValue might be negative:
  1675.     LONG32 lDelay =
  1676.     (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
  1677.     m_pSourceElement->m_lBeginEventClockValue;
  1678.     // /If delay is not set, don't add it!:
  1679.     if(pEventElement->m_bDelaySet)
  1680.     {
  1681. lDelay += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
  1682. // /Fixes case where dur already accounts for begin offset
  1683. // that's already built into the delay (e.g., begin="x.end-5"
  1684. // where x has an explicit begin offset greater than zero):
  1685. // /Helps fix PR 82736 (=x.begin case) by looking at flag and
  1686. // not just blindly assuming beginOffset is included in
  1687. // eventElement's m_ulDuration:
  1688. if (pEventElement->m_pSourceElement->
  1689. m_bDurationIncludesDelayBeyondSyncbase)
  1690. {
  1691.     HX_ASSERT((UINT32)-1 != pEventElement->m_pSourceElement->
  1692.     m_ulBeginOffsetFromSyncBase);
  1693.     if ((UINT32)-1 != pEventElement->m_pSourceElement->
  1694.     m_ulBeginOffsetFromSyncBase)
  1695.     {
  1696. lDelay -= (LONG32)pEventElement->m_pSourceElement->
  1697. m_ulBeginOffsetFromSyncBase;
  1698.     }
  1699. }
  1700. // /Fixes case where third ref has begin="second.end" and
  1701. // second has begin="first.end" where first.end is > 0.
  1702. // In that case, begin offset won't be set but delay WILL
  1703. // alread be part of the duration:
  1704. else if (pEventElement->m_pSourceElement->m_ulDelay >
  1705. pSyncBaseNode->m_pElement->m_ulDelay)
  1706. {
  1707.     ULONG32 ulDelayFromSyncBase =
  1708.     pEventElement->m_pSourceElement->m_ulDelay -
  1709.     pSyncBaseNode->m_pElement->m_ulDelay;
  1710.     HX_ASSERT(lDelay>(LONG32)ulDelayFromSyncBase);
  1711.     if (lDelay < (LONG32)ulDelayFromSyncBase)
  1712.     {
  1713. ulDelayFromSyncBase = lDelay;
  1714.     }
  1715.     lDelay -= (LONG32)ulDelayFromSyncBase;
  1716. }
  1717.     }
  1718.     // /Fixes PR 82736 (begin=x.end... case) where sync-arc begin
  1719.     // results in negative offset from parent and we've already
  1720.     // adjusted for that:
  1721.     if (pSyncBaseNode->m_pElement->m_ulDelay > lDelay  &&
  1722.     // /If already inserted, then adjustForNegativeOffset()
  1723.     // won't re-do any adjustment:
  1724.     m_pSourceElement->m_bInsertedIntoTimeline  &&
  1725.     !m_pSourceElement->m_bIsRestarting)
  1726.     {
  1727. // /Don't go earlier than synbase:
  1728. lDelay = pSyncBaseNode->m_pElement->m_ulDelay;
  1729.     }
  1730.     m_pSourceElement->m_ulDelay = lDelay<0? 0: (ULONG32)lDelay;
  1731.     if (lDelay < 0)
  1732.     {
  1733. UINT32 ulDiff = (UINT32)(-lDelay);
  1734. // /If clip-begin is invalid, set it otherwise add to orig:
  1735. m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
  1736.         m_pSourceElement->m_ulAuthoredClipBegin? ulDiff :
  1737. ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
  1738. if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
  1739. {
  1740.     if (m_pSourceElement->m_ulDuration > ulDiff)
  1741.     {
  1742. m_pSourceElement->m_ulDuration -= ulDiff;
  1743.     }
  1744.     // /else duration is negative; it can't ever play:
  1745.     else
  1746.     {
  1747. m_pSourceElement->m_ulDuration = 0;
  1748. #if defined(XXXEH_TESTING)
  1749. HX_ASSERT(m_pSourceElement->m_ulDuration);
  1750. #endif
  1751.     }
  1752. }
  1753.     }
  1754.     
  1755.     // /Now, if our begin delay (not offset) is based on a syncArc,
  1756.     // we need to adjust our dur by the difference between our delay
  1757.     // and our syncBase element's delay:
  1758.     if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
  1759.     m_pSourceElement->m_bEndOffsetSet  &&
  1760.     WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
  1761.     {
  1762. LONG32 lSum = m_pSourceElement->m_lEndOffset;
  1763. // /We need to remove our delay or it will get counted twice
  1764. lSum -= m_pSourceElement->m_ulDelay;
  1765. m_pSourceElement->m_ulDuration = (UINT32)(lSum<0 ? 0 : lSum);
  1766.     }
  1767.     bNeedToResolveBeginTimeListVals = TRUE;
  1768.     if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
  1769.     {
  1770. if (!m_pSourceElement->m_bHasBeenScheduled  ||
  1771. // /Fixes PR 50588 (case2): if restarting, hasBeenSched
  1772. // will still be true, so check if inserted instead:
  1773. (m_pSourceElement->m_bIsRestarting  &&
  1774. !m_pSourceElement->m_bInsertedIntoTimeline) )
  1775. {
  1776.     // /See note in code above that handles
  1777.     // m_nBeginEventSourceTag == SMILEventSourceBegin:
  1778.     BOOL bDelayIsBeyondParentEnd = FALSE;
  1779.     if ((UINT32)-1 != ulParentEnd)
  1780.     {
  1781. bDelayIsBeyondParentEnd =
  1782. (m_pSourceElement->m_ulDelay > ulParentEnd);
  1783.     }
  1784.     BOOL bInsertElement = bIsInExcl?
  1785.     (bDelayIsBeyondParentEnd  &&
  1786.     !bCantExtendParentDuration) :
  1787.     ( !(bDelayIsBeyondParentEnd  &&
  1788.     bCantExtendParentDuration) );
  1789.     // /But hold on: if parent's delay isn't yet resolved,
  1790.     // then we can't be inserted until it resolves.  Found
  1791.     // this while fixing long-sync-arc bug PR 64498, par test:
  1792.     // "..._longSyncArcBug-ParWithoutDur...sync.smil":
  1793.     BOOL bParentDelayIsUnresolved = FALSE;
  1794.     if ((UINT32)-1 == pSyncBaseNode->m_pElement->m_ulDelay  ||
  1795.     (pSyncBaseNode->m_pElement->m_pTimelineElement  &&
  1796.     pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelayEvent  &&
  1797.     !pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelaySet ))
  1798.     {
  1799. bInsertElement = FALSE;
  1800. bParentDelayIsUnresolved = TRUE;
  1801.     }
  1802.     if (m_pSourceElement->m_bBeginOffsetSet)
  1803.     {
  1804. // /If it's already been set, then just add this
  1805. // newly-resolved begin time to the pending queue
  1806. // and let it get sorted out there.  This can
  1807. // happen with begin="0s; foo.begin"
  1808. bInsertElement = FALSE;
  1809.     }
  1810.     if (!bInsertElement)
  1811.     {
  1812. // /See note in code above that handles
  1813. // m_nBeginEventSourceTag == SMILEventSourceBegin:
  1814. m_bDelaySet = bPreviousDelaySetVal;
  1815. // /Fixes "foo.end" version of PR 64498: flag the fact
  1816. // that long sync-arc begin is resolving before parent
  1817. // begin is resolved:
  1818. if (bParentDelayIsUnresolved)
  1819. {
  1820.     m_pSourceElement->
  1821. m_bAwaitingSyncAncestorBeginNotification = TRUE;
  1822.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1823.     lDelay;
  1824. }
  1825. // /This else-if is the final fix for foo.end version of
  1826. // PR 64499: if sync-base has multiple begin times, then
  1827. // we also need to prepare for that event restarting it
  1828. // even though its first begin is already resolved:
  1829. else if (pSyncBaseNode->m_pElement->m_pBeginTimeList  &&
  1830. pSyncBaseNode->m_pElement->m_pBeginTimeList->
  1831. GetCount() > 1)
  1832. {
  1833.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1834.     lDelay;
  1835. }
  1836. else
  1837. {
  1838.     m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1839.     (UINT32)-1;
  1840. }
  1841.     }
  1842.     else
  1843.     {
  1844. bWasInsertedOntoTimeline = TRUE;
  1845. m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
  1846.     (UINT32)-1;
  1847. m_pParser->insertTimelineElement(m_pID, 
  1848. m_pSourceElement->m_ulDelay);
  1849.     }
  1850. }
  1851. // /Fixes (part of) SMIL 2.0 Interop Timing #28.9:
  1852. // If already scheduled and possibly even playing, we need to
  1853. // reset the timeline element's delay:
  1854. else if (ulPriorDelay != m_pSourceElement->m_ulDelay)
  1855. {
  1856.     // /Get the matching begin time val, resolve it, and put
  1857.     // it in the pending list:
  1858.     LISTPOSITION lPos = NULL;
  1859.     if (m_pSourceElement->m_pBeginTimeList  &&  NULL !=
  1860.     (lPos = m_pSourceElement->m_pBeginTimeList->
  1861.     GetHeadPosition()) )
  1862.     {
  1863. while (lPos)
  1864. {
  1865.     SmilTimeValue* pTmpVal = (SmilTimeValue*)
  1866.     m_pSourceElement->m_pBeginTimeList->
  1867.     GetNext(lPos);
  1868.     if (pTmpVal)
  1869.     {
  1870. if (SmilTimeSyncBase == pTmpVal->m_type)
  1871. {
  1872.     if (!pTmpVal->isTimeResolved())
  1873.     {
  1874. if (pTmpVal->m_idRef ==
  1875. pEventElement->m_pID)
  1876. {
  1877.     BOOL bATimeWasResolved;
  1878.     m_pSourceElement->resolveSyncArcTimeValues(
  1879.     m_pSourceElement->m_ulDelay +
  1880.     (bUseBeginOffsetForPendingBeginList?
  1881.     m_pSourceElement->m_lBeginOffset:0),
  1882.     (const char*)pEventElement->m_pID,
  1883.     SmilBeginTimeList, bATimeWasResolved,
  1884.     TRUE, m_pParser);
  1885.     bNeedToResolveBeginTimeListVals = FALSE;
  1886. }
  1887.     }
  1888.     else
  1889.     {
  1890. // /else get from pending and change it!
  1891. // See PR 50588 (case 2: begin="x.end")
  1892.     }
  1893. }
  1894.     }
  1895. }
  1896.     }
  1897. }
  1898.     }
  1899. }
  1900.     }
  1901.     SMILNode* pSyncNode = pSyncBaseNode;
  1902.     HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
  1903.     //[SMIL 1.0 compliance] Fixes PR 16629:
  1904.     //Next, let's see if we have an end event to resolve:
  1905.     // /XXXEH- TODO 20010525: we need to see if there already is an end time
  1906.     // that is prior to this new one and is after a begin time; if so, then
  1907.     // we want to stick this new one into the pending end time list rather
  1908.     // than use it right away:
  1909.     // /Combining handling of SMILEventSourceBegin and SMILEventSourceClock
  1910.     // fixes SMIL 1.0-syntax version of PR 63622 (part 4) where the fix for
  1911.     // part 2 gets resused if we share this code; it's about time we combine
  1912.     // this code, anyway:
  1913.     if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
  1914.     m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
  1915.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  1916.     {
  1917. if(pEventElement->m_bDelaySet)
  1918. {
  1919.     m_bDurationSet = TRUE;
  1920.     LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  1921.          m_pSourceElement->m_lEndEventClockValue;
  1922.     // /Now, if our begin delay (not offset) is based on a syncArc,
  1923.     // we need to adjust our dur by the difference between our delay
  1924.     // and our syncBase element's delay:
  1925.     if (m_pSourceElement->m_bBeginOffsetSet)
  1926.     {
  1927. if (pSyncNode  &&  pSyncNode->m_pElement)
  1928. {
  1929.     ULONG32 ulSyncBaseDelay =
  1930.     pSyncNode->m_pElement->m_ulDelay;
  1931.     HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
  1932.     if ((UINT32)-1 != ulSyncBaseDelay)
  1933.     {
  1934. HX_ASSERT(m_pSourceElement->m_ulDelay >=
  1935. ulSyncBaseDelay);
  1936. if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay)
  1937. {
  1938.     lSum -= (LONG32)ulSyncBaseDelay;
  1939. }
  1940.     }
  1941. }
  1942.     }
  1943.     // /Checking these two conditionals helps fix PR 63622 (part 2):
  1944.     else if (m_bDelaySet  &&  m_pSourceElement->m_ulDelay!=(UINT32)-1)
  1945.     {
  1946. // /We need to remove our delay or it will get counted twice:
  1947. lSum -= m_pSourceElement->m_ulDelay;
  1948.     }
  1949.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  1950.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  1951.     m_pSourceElement->m_ulDuration = (UINT32)lSum;
  1952.     // /Fixes case where parent dur was overriding this new
  1953.     // m_ulDuration, above, in this's subsequent setDuration(d,TRUE)
  1954.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulAuthoredDur)
  1955.     {
  1956. // /Change "core-tricking" value back to unset:
  1957. m_pSourceElement->m_ulAuthoredDur = (UINT32)-1;
  1958.     }
  1959.     // /Fixes case where both dur=d & end=x.begin were specified;
  1960.     // use the lesser of the two (part 4 of PR 71386):
  1961.     else if (m_pSourceElement->m_bHasExplicitDur  &&
  1962.     (UINT32)-1 != m_pSourceElement->m_ulAuthoredDur  &&
  1963.     m_pSourceElement->m_ulAuthoredDur < (UINT32)lSum)
  1964.     {
  1965. m_pSourceElement->m_ulDuration =
  1966. m_pSourceElement->m_ulAuthoredDur;
  1967.     }
  1968.     bNeedToResolveEndTimeListVals = TRUE;
  1969.     // /More of fix for PR 63622 (part 2): if our delay isn't set, then
  1970.     // when it does resolve, treat it as an end, not a relative dur:
  1971.     if (!m_bDelaySet  ||  m_pSourceElement->m_ulDelay==(UINT32)-1)
  1972.     {
  1973. /* Removing this doesn't (now) affect PR 63622 part 2, which
  1974.  * still plays fine, while removing it *does* fix PR 81256
  1975.  * where an element wasn't restarting because its end time
  1976.  * (in its list) wasn't considered resolved on the next play:
  1977. // /For PR 63622 (part 2): don't resolve end time(s) since
  1978. // begin delay isn't resolved yet:
  1979. bNeedToResolveEndTimeListVals = FALSE;
  1980.  */
  1981. if (!m_pSourceElement->m_bEndOffsetSet)
  1982. {
  1983.     m_pSourceElement->m_bEndOffsetSet = TRUE;
  1984.     m_pSourceElement->m_lEndOffset = (UINT32)lSum;
  1985. }
  1986.     }
  1987.     // /Helps fix PR 63622 (part 2): changed this to "*else* if" since
  1988.     //  we don't want to do anything until our begin delay is set:
  1989.     else if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
  1990.     {
  1991. if (!m_pSourceElement->m_bHasBeenScheduled  ||
  1992. // /Fixes PR 50588 (case4): if restarting, hasBeenSched
  1993. // will still be true, so check if inserted instead:
  1994. (m_pSourceElement->m_bIsRestarting  &&
  1995. !m_pSourceElement->m_bInsertedIntoTimeline) )
  1996. {
  1997.     bWasInsertedOntoTimeline = TRUE;
  1998.     m_pParser->insertTimelineElement(m_pID, 
  1999. m_pSourceElement->m_ulDelay);
  2000. }
  2001. // /Be sure to update the timeline; fixes variant of PR 59801
  2002. // when end="x.begin" instead of end="x.end":
  2003. else
  2004. {
  2005.     m_pParser->resetTimelineElementDuration(
  2006.     (const char*)m_pSourceElement->m_pNode->m_id,
  2007.     m_pSourceElement->getPureDuration(),
  2008.     ulPriorPureDuration);
  2009.     m_pParser->m_pTimelineElementManager->notify(
  2010.     (const char*)m_pSourceElement->m_pNode->m_id);
  2011. }
  2012.     }
  2013. }
  2014.     }
  2015.     else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
  2016.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  2017.     {
  2018. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  2019. // essentially an unresolved end time, so we should not resolve
  2020. // based on it:
  2021. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  2022. pEventElement->m_pSourceElement->m_ulDuration)
  2023. {
  2024.     m_bDurationSet = TRUE;
  2025.     LONG32 lSum =(LONG32)pEventElement->getDuration() +
  2026.     m_pSourceElement->m_lEndEventClockValue;
  2027.     // /If the event element has a delay, we need to add that
  2028.     // minus any beginOffset (if it's set); subtracting the begin
  2029.     // offset fixes "BUG-20000921_beginSyncArcOffBy5secInBlue.smi":
  2030.     if(pEventElement->m_bDelaySet)
  2031.     {
  2032. lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
  2033. if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
  2034. pEventElement->m_pSourceElement->m_lBeginOffset > 0)
  2035. {
  2036.     lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
  2037.     // /20020630- Find content that may be broken if this
  2038.     // asserts.  If such a thing exists, change above call to
  2039.     // "...->getDuration()" to "...->getPureDuration()" and
  2040.     // then total delay:
  2041.     HX_ASSERT(pEventElement->m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
  2042. }
  2043. // /Final nail in PR 77406's coffin: if begin of event element
  2044. // was event based and thus there's no m_bBeginOffsetSet but
  2045. // there *is* a m_ulBeginOffsetFromSyncBase>0, then we need to
  2046. // subtract that if it's included in the duration:
  2047. else if (pEventElement->m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
  2048. pEventElement->m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  2049. pEventElement->m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
  2050. {
  2051.     lSum -= pEventElement->m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2052. }
  2053.     }
  2054.     else
  2055.     {
  2056. HX_ASSERT(pEventElement->m_bDelaySet);
  2057.     }
  2058.     // /lSum is now in global (group) time space.  We need to convert
  2059.     // it into this's local time space:
  2060.     // /Now, if our begin delay (not offset) is based on a syncArc,
  2061.     // we need to adjust our dur by the difference between our delay
  2062.     // and our syncBase element's delay:
  2063.     if (m_pSourceElement->m_bBeginOffsetSet)
  2064.     {
  2065. if (pSyncNode  &&  pSyncNode->m_pElement)
  2066. {
  2067.     ULONG32 ulSyncBaseDelay =
  2068.     pSyncNode->m_pElement->m_ulDelay;
  2069.     HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
  2070.     if ((UINT32)-1 != ulSyncBaseDelay)
  2071.     {
  2072. HX_ASSERT(m_pSourceElement->m_ulDelay >=
  2073. ulSyncBaseDelay);
  2074. if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay)
  2075. {
  2076.     lSum -= (LONG32)ulSyncBaseDelay;
  2077. }
  2078.     }
  2079. }
  2080. // /This fixes PR 8XXXZ (PR 63622 revisited): if begin is set and duration includes
  2081. // that begin delay, subtract it from the sum & reset the flag:
  2082. if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
  2083.     m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
  2084. {
  2085.     lSum -= m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0?
  2086.     m_pSourceElement->m_ulBeginOffsetFromSyncBase : 0;
  2087.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  2088.     FALSE;
  2089. }
  2090.     }
  2091.     // /Checking these two conditionals helps fix PR 63622 (part 3):
  2092.     else if (m_bDelaySet  &&  m_pSourceElement->m_ulDelay!=(UINT32)-1)
  2093.     {
  2094. // /We need to remove our delay or it will get counted twice:
  2095. // /XXXEH- 20020625: maybe subtract curBeginOffsetFromSyncBase (as 10 lines above) instead?:
  2096. lSum -= m_pSourceElement->m_ulDelay;
  2097.     }
  2098.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2099.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2100.     m_pSourceElement->m_ulDuration = (UINT32)lSum;
  2101.             BOOL bDurationWasPreviouslyUnresolvedIndefinite = FALSE;
  2102.     // /Fixes case where parent dur was overriding this new
  2103.     // m_ulDuration, above, in this's subsequent setDuration(d,TRUE)
  2104.     if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulAuthoredDur)
  2105.     {
  2106.                 bDurationWasPreviouslyUnresolvedIndefinite = TRUE;
  2107. // /Change "core-tricking" value back to unset:
  2108. m_pSourceElement->m_ulAuthoredDur = (UINT32)-1;
  2109.     }
  2110.     // /Fixes case where both dur=d & end=x.end were specified;
  2111.     // use the lesser of the two (part 2 of PR 71386):
  2112.     else if (m_pSourceElement->m_bHasExplicitDur  &&
  2113.     (UINT32)-1 != m_pSourceElement->m_ulAuthoredDur  &&
  2114.     m_pSourceElement->m_ulAuthoredDur < (UINT32)lSum)
  2115.     {
  2116. m_pSourceElement->m_ulDuration =
  2117. m_pSourceElement->m_ulAuthoredDur;
  2118.     }
  2119.     bNeedToResolveEndTimeListVals = TRUE; 
  2120.   
  2121.     // /More of fix for PR 63622 (part 3): if our delay isn't set, then 
  2122.     // when it does resolve, treat it as an end, not a relative dur: 
  2123.     if (!m_bDelaySet  ||  m_pSourceElement->m_ulDelay==(UINT32)-1) 
  2124.     { 
  2125. /* Removing this doesn't (now) affect PR 63622 part 3, which
  2126.  * still plays fine, while removing it *does* fix PR 81256
  2127.  * where an element wasn't restarting because its end time
  2128.  * (in its list) wasn't considered resolved on the next play:
  2129. // /For PR 63622 (part 3): don't resolve end time(s) since 
  2130. // begin delay isn't resolved yet: 
  2131. bNeedToResolveEndTimeListVals = FALSE;
  2132.  */
  2133. if (!m_pSourceElement->m_bEndOffsetSet) 
  2134.     m_pSourceElement->m_bEndOffsetSet = TRUE; 
  2135.     m_pSourceElement->m_lEndOffset = (UINT32)lSum; 
  2136.     } 
  2137.     // /Helps fix PR 63622 (part 3): changed this to "*else* if" since 
  2138.     //  we don't want to do anything until our begin delay is set: 
  2139.     else if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID)) 
  2140.     {
  2141. if (!m_pSourceElement->m_bHasBeenScheduled  ||
  2142. // /Fixes PR 50588 (case5): if restarting, hasBeenSched
  2143. // will still be true, so check if inserted instead:
  2144. (m_pSourceElement->m_bIsRestarting  &&
  2145. !m_pSourceElement->m_bInsertedIntoTimeline) )
  2146. {
  2147.     bWasInsertedOntoTimeline = TRUE;
  2148.     m_pParser->insertTimelineElement(m_pID, 
  2149. m_pSourceElement->m_ulDelay);
  2150. }
  2151. // /Fixes PR 59801: the fix for PR 50535, which enabled
  2152. // inserting of an element into the timeline before its end
  2153. // event is resolved (as is needed when end="foo.end" and foo
  2154. // has an event-based end) caused parent to extend to that
  2155. // WAY_IN_THE_FUTURE dur and never brought it back in when
  2156. // the end time resolved, so here goes:
  2157.                 // /Adding the if() part to the else helps fix PR 107724: don't
  2158.                 // go through all this code if this element has not had its
  2159.                 // duration altered by the code, above:
  2160.                 else if (m_pSourceElement->getPureDuration() !=
  2161.                         ulPriorPureDuration)
  2162. {
  2163.     // /This fixes PR 70437 where temporary, indefinite
  2164.     // duration had been added to parent, earlier, while
  2165.     // waiting for when (or if) sync-arc'd element's end
  2166.     // ever resolves.  Then, when it resolved, parent wasn't
  2167.     // being notified of this new duration, thus the temporary
  2168.     // indef duration remained as the presentation duration:
  2169.     m_bDurationSet=FALSE; // /Force override to new value.
  2170.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  2171.     m_pSourceElement->getPureDuration());
  2172.     m_pParser->durationResolved(
  2173.     (const char*)m_pSourceElement->m_pNode->m_id,
  2174.     m_pSourceElement->m_ulDuration, FALSE);
  2175.     m_pParser->resetTimelineElementDuration(
  2176.     (const char*)m_pSourceElement->m_pNode->m_id,
  2177.     m_pSourceElement->getPureDuration(),
  2178.     ulPriorPureDuration);
  2179.                     // /Helps fix PR 107724: add duration to parent if
  2180.                     // it was added before as unresolved indefinite:
  2181.                     if (m_pSourceElement->m_bAddDurationAlreadyDone  &&
  2182.                             bDurationWasPreviouslyUnresolvedIndefinite)
  2183.                     {
  2184.                         m_pParent->addDuration( 
  2185.                                 m_pSourceElement->m_ulDuration, 
  2186.                                 m_pSourceElement->m_ulDelay,
  2187.                                 m_pSourceElement->m_ulBeginOffsetFromSyncBase,
  2188.                                 m_pID);
  2189.                     }
  2190.     m_pParser->m_pTimelineElementManager->notify(
  2191.     (const char*)m_pSourceElement->m_pNode->m_id);
  2192. }
  2193.     }
  2194. }
  2195.     }
  2196.     BOOL bMoveNewlyResolvedsToPendingTimeList =
  2197.     !bWasInsertedOntoTimeline;
  2198.     if (bNeedToResolveBeginTimeListVals)
  2199.     {
  2200. BOOL bATimeWasResolved;
  2201. m_pSourceElement->resolveSyncArcTimeValues(
  2202. m_pSourceElement->m_ulDelay +
  2203. (bUseBeginOffsetForPendingBeginList?
  2204. m_pSourceElement->m_lBeginOffset:0),
  2205. (const char*)pEventElement->m_pID,
  2206. SmilBeginTimeList, bATimeWasResolved,
  2207. bMoveNewlyResolvedsToPendingTimeList,
  2208. m_pParser);
  2209.     }
  2210.     if (bNeedToResolveEndTimeListVals)
  2211.     {
  2212. // /Fixes PR 81828: if delay is unresolved but end time was just
  2213. // resolved, above, then use end not the invalid sum of dur+delay:
  2214. ULONG32 ulEndTime = m_pSourceElement->m_ulDuration +
  2215. m_pSourceElement->m_ulDelay;
  2216. if ((UINT32)-1 == m_pSourceElement->m_ulDelay  ||
  2217. (UINT32)-1 == m_pSourceElement->m_ulDuration)
  2218. {
  2219.     ulEndTime = m_pSourceElement->m_lEndOffset;
  2220. }
  2221. // /Helps fix PR 79699 (case where trackDurationResolved call order
  2222. // is: flash, msd, vid):
  2223. else if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
  2224. m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
  2225. {
  2226.     ulEndTime -= m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2227. }
  2228. BOOL bATimeWasResolved;
  2229. m_pSourceElement->resolveSyncArcTimeValues(
  2230. // /Use dur+delay, not just delay here (as can be proven when
  2231. // doing the following: begin="foo.end" end="foo.end+5s"
  2232. // where foo.begin > 0:
  2233. ulEndTime,
  2234. (const char*)pEventElement->m_pID,
  2235. SmilEndTimeList, bATimeWasResolved,
  2236. bMoveNewlyResolvedsToPendingTimeList,
  2237. m_pParser);
  2238.     }
  2239.     // XXXMEH - we need to check here if we should
  2240.     // update the remove time
  2241.     checkElementFillBehavior();
  2242. }
  2243. #if 0
  2244. void
  2245. CSmilTimelineElement::setEvent(SMILEventSourceTag eTag,
  2246. SMILSyncAttributeTag aTag,
  2247. const char* pEventSourceID,
  2248. UINT32 ulEventClockValue)
  2249. {
  2250.     m_eEventSourceTag = eTag;
  2251.     m_eSyncAttributeTag = aTag;
  2252.     if(pEventSourceID)
  2253.     {
  2254. m_pEventSourceID = new char[strlen(pEventSourceID)+1];
  2255. strcpy(m_pEventSourceID, pEventSourceID); /* Flawfinder: ignore */
  2256. m_pParser->m_pTimelineElementManager->addNotification(pEventSourceID, this);
  2257.     }
  2258.     m_ulEventClockValue = ulEventClockValue;
  2259. }
  2260. #endif
  2261. void 
  2262. CSmilTimelineElement::addChild(CSmilTimelineElement* pChild)
  2263. {
  2264.     if(!m_pChildren)
  2265.     {
  2266. m_pChildren = new CHXSimpleList;
  2267.     }
  2268.     m_pChildren->AddTail(pChild);
  2269.     pChild->setParent(this);
  2270. }
  2271. UINT32
  2272. CSmilTimelineElement::getDuration()
  2273. {
  2274.     return m_pSourceElement->m_ulDuration;
  2275. }
  2276. UINT32
  2277. CSmilTimelineElement::getDelay()
  2278. {
  2279.     return m_pSourceElement->m_ulDelay;
  2280. }
  2281. void 
  2282. CSmilTimelineElement::dump()
  2283. {
  2284. }
  2285. void CSmilTimelineElement::checkChildrenFillBehavior()
  2286. {
  2287.     if (m_pChildren && m_pParser)
  2288.     {
  2289.         LISTPOSITION pos = m_pChildren->GetHeadPosition();
  2290.         while (pos)
  2291.         {
  2292.             CSmilTimelineElement* pTime =
  2293.                 (CSmilTimelineElement*) m_pChildren->GetNext(pos);
  2294.             if (pTime &&
  2295.                 pTime->m_pSourceElement &&
  2296.                 pTime->m_pSourceElement->m_pNode)
  2297.             {
  2298.                 const char* pszID          = (const char*) pTime->m_pSourceElement->m_pNode->m_id;
  2299.                 UINT32      ulComputedTime = 0;
  2300.                 HX_RESULT   retVal         = m_pParser->computeRemoveTime(pszID, ulComputedTime);
  2301.                 if (SUCCEEDED(retVal))
  2302.                 {
  2303. // /#define XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT
  2304. #if defined(_DEBUG)  &&  defined(XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT)
  2305. {
  2306.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
  2307.     ::fprintf(f1, "checkChildrenFillBehavior() of %s, computed time=%lu, m_ulRemoveTime=%lu, m_ulDelay=%lu, m_ulDuration=%lun",
  2308. pszID, ulComputedTime, pTime->m_pSourceElement->m_ulRemoveTime, pTime->m_pSourceElement->m_ulDelay, pTime->m_pSourceElement->m_ulDuration);
  2309.     ::fclose(f1);
  2310. }
  2311. #endif
  2312.                     // We've successfully computed the remove time - does
  2313.                     // this remove time match when we have the hide event scheduled?
  2314.                     if (ulComputedTime != pTime->m_pSourceElement->m_ulRemoveTime)
  2315.                     {
  2316. #if defined(_DEBUG)  &&  defined(XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT)
  2317. {
  2318.     FILE* f1 = ::fopen("c:\smil2excl.txt", "a+");
  2319.     ::fprintf(f1, "tcheckChildrenFillBehavior() called [%s]->updateRemoveTime(%lu   <--(%lu) ), m_ulDelay=%lu, m_ulDuration=%lun",
  2320. pszID, ulComputedTime, pTime->m_pSourceElement->m_ulRemoveTime, pTime->m_pSourceElement->m_ulDelay, pTime->m_pSourceElement->m_ulDuration);
  2321.     ::fclose(f1);
  2322. }
  2323. #endif
  2324.                         // We need to update the hide event
  2325.                         pTime->m_pSourceElement->updateRemoveTime(ulComputedTime);
  2326.                     }
  2327.                     // If this child has a fill="freeze" or a fill="hold",
  2328.                     // then we need to check this child's children
  2329.                     if (pTime->m_pSourceElement->m_eActualFill == FillFreeze ||
  2330.                         pTime->m_pSourceElement->m_eActualFill == FillHold)
  2331.                     {
  2332.                         pTime->checkChildrenFillBehavior();
  2333.                     }
  2334.                 }
  2335.             }
  2336.         }
  2337.     }
  2338. }
  2339. void CSmilTimelineElement::checkElementFillBehavior()
  2340. {
  2341.     if (m_pSourceElement &&
  2342.         m_pSourceElement->m_pNode)
  2343.     {
  2344.         const char* pszID          = (const char*) m_pSourceElement->m_pNode->m_id;
  2345.         UINT32      ulComputedTime = 0;
  2346.         HX_RESULT   retVal         = m_pParser->computeRemoveTime(pszID, ulComputedTime);
  2347.         if (SUCCEEDED(retVal))
  2348.         {
  2349.             // We've successfully computed the remove time - does
  2350.             // this remove time match when we have the hide event scheduled?
  2351.             if (ulComputedTime != m_pSourceElement->m_ulRemoveTime)
  2352.             {
  2353. //                char szDbgStr[128];
  2354. //                DEBUGPRINTF(szDbgStr, "Updating id=%s remove time from %lu to %lun",
  2355. //                            pszID, m_pSourceElement->m_ulRemoveTime, ulComputedTime);
  2356.                 // We need to update the hide event
  2357.                 m_pSourceElement->updateRemoveTime(ulComputedTime);
  2358.             }
  2359.         }
  2360.     }
  2361. }
  2362. void CSmilTimelineElement::setParExclDuration(UINT32 ulDuration, BOOL bSetFromParent)
  2363. {
  2364.     m_pSourceElement->m_ulDuration = ulDuration;
  2365.     // /Don't go past end of parent; fixes PR65741-related event-begun par
  2366.     if (m_pSourceElement->m_ulDuration > m_pSourceElement->m_ulMaxDuration)
  2367.     {
  2368. m_pSourceElement->m_ulDuration = m_pSourceElement->m_ulMaxDuration;
  2369.     }
  2370.     m_bDurationSet = TRUE;
  2371.     if(m_pChildren  &&
  2372.     // /If not set from parent, make sure we've completely resolved
  2373.     // our duration before forcing it on the kids (broken by fix for
  2374.     // PR 61174(version1).  Fixes PR 56686 version 7:
  2375.     (bSetFromParent  ||  m_pSourceElement->m_bAddDurationAlreadyDone
  2376.     // /Explicit end or dur, so OK to possibly clip children; helps
  2377.     // reduce cases where PR 65676 occurs by setting max durs on kids:
  2378.     ||  m_pSourceElement->m_bHasExplicitEnd
  2379.     ||  m_pSourceElement->m_bHasExplicitDur))
  2380.     {
  2381. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2382. for(; i != m_pChildren->End(); ++i)
  2383. {
  2384.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2385.     pElement->setDuration(m_pSourceElement->m_ulDuration, TRUE);
  2386.         }
  2387.     }
  2388.     //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025
  2389.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  2390. }
  2391. void CSmilTimelineElement::setParExclMaxDuration(UINT32 ulMaxDuration)
  2392. {
  2393.     HX_ASSERT(m_pChildren);
  2394.     m_bMaxDurationSet = TRUE;
  2395.     m_pSourceElement->m_ulMaxDuration = ulMaxDuration;
  2396.     if (m_pChildren  &&  m_bDelaySet)
  2397.     {
  2398. HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  2399. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2400. for(; i != m_pChildren->End(); ++i)
  2401. {
  2402.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2403.     pElement->setMaxDuration(ulMaxDuration);
  2404. }
  2405.     }
  2406. }
  2407. void CSmilTimelineElement::parExclElementResolved(CSmilTimelineElement* pEventElement)
  2408. {
  2409.     // /Fixes PR 56233 (par version): if this par is resolving an end time
  2410.     // based on another element's timing and that other element is a
  2411.     // descendant of this par, then we'll get in an infinite loop when this
  2412.     // par clips its child's end, causing the child to update its end, causing
  2413.     // this par to get another elementResolved, ad infinitum.  Now, we lock
  2414.     // elementResolved() on this element by setting its m_bInElementResolved
  2415.     // flag and resetting it only when this method has completed:
  2416.     if (m_bInElementResolved)
  2417.     {
  2418. goto cleanup;
  2419.     }
  2420.     m_bInElementResolved = TRUE;
  2421.     //First, let's see if we have a begin event to resolve:
  2422.     // /Combine handling of SMILEventSourceBegin and SMILEventSourceClock;
  2423.     // the latter is only used in SMIL 1.0-syntax syncArcs with clock offsets:
  2424.     if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
  2425.     m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
  2426.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
  2427.     {
  2428. if(pEventElement->m_bDelaySet)
  2429. {
  2430.     // /Note: no longer subtracting pEventElement->m_pSourceElement->
  2431.     // m_ulBeginOffsetFromSyncBase from the sum in the following
  2432.     // if/else fixes PR 66352 while allowing PR 14420 (SMIL2-excl
  2433.     // version) to still work
  2434.     //[SMIL 1.0 Compliance] Helps fix 14420:
  2435.     if (m_bNonEventDelaySet)
  2436.     {
  2437. //Add non-event delay to syncArc element delay + clock offset:
  2438. //Do the following in case sum is negative; if so, we
  2439. // want to use zero.
  2440. LONG32 lSum =
  2441. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2442. m_pSourceElement->m_lBeginEventClockValue;
  2443. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2444. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2445. m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
  2446.     }
  2447.     else
  2448.     {
  2449. //Just set delay to syncArc element delay + clock offset:
  2450. //Do the following in case sum is negative; if so, we
  2451. // want to use zero.
  2452. LONG32 lSum =
  2453. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2454. m_pSourceElement->m_lBeginEventClockValue;
  2455. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2456. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2457. m_pSourceElement->m_ulDelay = (ULONG32)lSum;
  2458. m_ulNonEventDelay = 0;
  2459.     }
  2460.     m_bNonEventDelaySet = m_bDelaySet = TRUE;
  2461.     if(m_pChildren)
  2462.     {
  2463. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2464. for(; i != m_pChildren->End(); ++i)
  2465. {
  2466.     CSmilTimelineElement* pElement =
  2467.     (CSmilTimelineElement*)(*i);
  2468.     pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  2469. }
  2470.     }
  2471. }
  2472.     }
  2473.     else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
  2474.     m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
  2475.     {
  2476. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  2477. // essentially an unresolved end time, so we should not resolve
  2478. // based on it:
  2479. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  2480. pEventElement->m_pSourceElement->m_ulDuration)
  2481. {
  2482.     //[SMIL 1.0 Compliance] Helps fix 14420:
  2483.     if (m_bNonEventDelaySet)
  2484.     {
  2485. //Add non-event delay to syncArc element end + clock offset:
  2486. LONG32 lSum =
  2487. (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
  2488. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2489. m_pSourceElement->m_lBeginEventClockValue;
  2490. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2491. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2492. m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
  2493.     }
  2494.     else
  2495.     {
  2496. //Just set delay to syncArc element end + clock offset:
  2497. //Do the following in case sum is negative; if so, we
  2498. // want to use zero.
  2499. LONG32 lSum =
  2500. (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
  2501. (LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2502. m_pSourceElement->m_lBeginEventClockValue;
  2503. HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2504. lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2505. m_pSourceElement->m_ulDelay = (ULONG32)lSum;
  2506. m_ulNonEventDelay = 0;
  2507.     }
  2508.     m_bNonEventDelaySet = m_bDelaySet = TRUE;
  2509.     if(m_pChildren)
  2510.     {
  2511. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2512. for(; i != m_pChildren->End(); ++i)
  2513. {
  2514.     CSmilTimelineElement* pElement =
  2515.     (CSmilTimelineElement*)(*i);
  2516.     pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  2517. }
  2518.     }
  2519. }
  2520.     }
  2521.     
  2522.     // /Combine handling of SMILEventSourceBegin and SMILEventSourceClock;
  2523.     // the latter is only used in SMIL 1.0-syntax syncArcs with clock offsets:
  2524.     if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
  2525.     m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
  2526.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  2527.     {
  2528. if(pEventElement->m_bDelaySet)
  2529. {
  2530.     LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
  2531.          m_pSourceElement->m_lEndEventClockValue;
  2532.     if (m_bDelaySet)
  2533.     {
  2534. // /Fixes bug where the following had a dur that didn't
  2535. // account for its offset:
  2536. // <par begin="3s" end="foo.begin+5s" />
  2537. lSum -= m_pSourceElement->m_ulDelay;
  2538.     }
  2539.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2540.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2541.     // /Fixes PR 43068:
  2542.     m_bDurationSet = FALSE; // /We want to force override to lSum.
  2543.     parExclDurationResolved((ULONG32)lSum, TRUE);
  2544. }
  2545.     }
  2546.     else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
  2547.     m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
  2548.     {
  2549. // /If event element's duration is "WAY_IN_THE_FUTURE" then it's
  2550. // essentially an unresolved end time, so we should not resolve
  2551. // based on it:
  2552. if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
  2553. pEventElement->m_pSourceElement->m_ulDuration)
  2554. {
  2555.     LONG32 lSum =(LONG32)pEventElement->getDuration() +
  2556.     m_pSourceElement->m_lEndEventClockValue;
  2557.     // /If the event element has a delay, we need to add that
  2558.     // minus any beginOffset (if it's set):
  2559.     if(pEventElement->m_bDelaySet)
  2560.     {
  2561. lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
  2562. if (pEventElement->m_pSourceElement->m_bBeginOffsetSet)
  2563. {
  2564.     HX_ASSERT(0  &&  "ehodge: does this code work?!");
  2565.     lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
  2566. }
  2567.     }
  2568.     if (m_bDelaySet)
  2569.     {
  2570. // /Fixes bug where the following had a dur that didn't
  2571. // account for its offset:
  2572. // <par begin="3s" end="foo.end+5s" />
  2573. lSum -= m_pSourceElement->m_ulDelay;
  2574.     }
  2575.     HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
  2576.     lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
  2577.     // /Fixes PR 43068:
  2578.     m_bDurationSet = FALSE; // /We want to force override to lSum.
  2579.     parExclDurationResolved((ULONG32)lSum, TRUE);
  2580. }
  2581.     }
  2582.     m_bInElementResolved = FALSE;
  2583. cleanup:
  2584.     return;
  2585. }
  2586. void CSmilTimelineElement::parExclDurationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
  2587. {
  2588. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  2589.     {
  2590. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  2591. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  2592. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  2593. ::fprintf(f1, "CSmilTimelineElement{%s}::parExclDurationResolved(dur=%lu, bUpdateChildren=%d, "
  2594. "m_bDurationSet=%sE (cur m_ulDuration=%lu) m_bAddDurationAlreadyDone=%dn",
  2595. (const char*)m_pID, ulDuration, bUpdateChildren, m_bDurationSet?"TRU":"FALS",
  2596. m_pSourceElement->m_ulDuration, m_pSourceElement->m_bAddDurationAlreadyDone);
  2597. ::fclose(f1);
  2598. bFirstTimeAddDurDebugout = FALSE;
  2599.     }
  2600. #endif
  2601.     if(!m_bDurationSet  ||
  2602.     // /Final fix for PR 52110: we need to make sure parent and
  2603.     // dependent, if any, get told of our duration even if our
  2604.     // duration has already been set, which can happen if we have
  2605.     // an explicit end or dur.  We should go ahead and add ourself to
  2606.     // the parent if we haven't already done so:
  2607.     !m_pSourceElement->m_bAddDurationAlreadyDone)
  2608.     {
  2609. // /(Note: if endsync="first" causes re-resolving of duration, then
  2610. // it's perfectly valid for bUpdateChildren to be TRUE here.)
  2611. m_bDurationSet = TRUE;
  2612. m_pSourceElement->m_ulDuration = ulDuration;
  2613. if(m_pParent)
  2614. {
  2615.     ULONG32 ulDelayFromSyncBaseBegin = 0;
  2616.     if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
  2617.     {
  2618. ulDelayFromSyncBaseBegin =
  2619. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2620. if (ulDelayFromSyncBaseBegin > 0  &&
  2621. !m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2622. {
  2623.     m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
  2624.     TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
  2625.     m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
  2626. }
  2627.     }
  2628.     m_pParent->addDuration(m_pSourceElement->m_ulDuration,
  2629.     m_pSourceElement->m_ulDelay,
  2630.     ulDelayFromSyncBaseBegin, m_pID);
  2631.     m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
  2632. }
  2633. if(m_pDependent)
  2634. {
  2635. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2636.     ULONG32 ulTotalDelay = 0;
  2637.     if (HXR_OK !=
  2638.     m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  2639.     {
  2640. goto doneSettingDependent;
  2641.     }
  2642. #else
  2643.     ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  2644.     m_pSourceElement->m_ulDuration;
  2645.     // /Helps fix PR 6XXXX(par version): if delay is already packed
  2646.     // into the duration, then don't count it twice (as can happen in
  2647.     // <seq><par begin="1s">...</par><par begin="1s" ...):
  2648.     if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2649.     {
  2650. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  2651. /*OK[]*/ if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
  2652. {
  2653.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2654.     ulTotalDelay);
  2655.     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2656.     ulTotalDelay)
  2657.     {
  2658. ulTotalDelay -=
  2659. m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2660.     }
  2661. }
  2662.     }
  2663. #endif
  2664.     if (WAY_IN_THE_FUTURE < ulTotalDelay)
  2665.     {
  2666. ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584 (par2).
  2667.     }
  2668.     // /helps fix PR 62688 (case2) where outer seq has media after
  2669.     // par w/endsync="all": don't adjustDep.Dur. if delay is indef.:
  2670.     if ((m_pDependent->getDelay() != (UINT32)-1  &&
  2671.     m_pDependent->getDelay() >= WAY_IN_THE_FUTURE)  ||
  2672.     // /Helps fix PR 59584 (parFollowsPar version): also don't
  2673.     // adjustDep.Dur. if we're about to set the delay to indef
  2674.     (m_pDependent->getDelay() == (UINT32)-1  &&
  2675.     WAY_IN_THE_FUTURE == ulTotalDelay) )
  2676.     {
  2677.     HX_ASSERT(ulTotalDelay==WAY_IN_THE_FUTURE  &&  "send content to ehodge");
  2678.     }
  2679.     else
  2680.     {
  2681. adjustDependentDuration(m_pDependent);
  2682.     }
  2683. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  2684. {
  2685.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  2686.     ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  2687.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  2688.     ::fprintf(f1, "nt%s:CSmilTimelineElement::parExclDurationResolved();tsetting dependent (%s)'s delay to %lun",
  2689.     (const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
  2690.     ::fclose(f1);
  2691.     bFirstTimeAddDurDebugout = FALSE;
  2692. }
  2693. #endif
  2694.     // /XXXEH- TODO: figure out if we need to claim this is being set
  2695.     // by "parent" (which is really time base) so clip-begin-like
  2696.     // action can occur; I don't think so, however:
  2697.     m_pDependent->setDelay(ulTotalDelay, FALSE);     
  2698. }
  2699. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2700. doneSettingDependent:
  2701. #endif
  2702. if(bUpdateChildren)
  2703. {
  2704.     UINT32 ulNumChildrenDursSet = 0;
  2705.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  2706.     for(; i != m_pChildren->End(); ++i)
  2707.     {
  2708. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2709. // /If child has no resolved, scheduled begin time yet, then
  2710. // for crying out loud don't set its duration yet.  This is
  2711. // needed in the case where *this has endsync="all":
  2712. if (SMILEventSourceAll !=
  2713. m_pSourceElement->m_nEndsyncEventSourceTag  ||
  2714. pElement->m_pSourceElement->m_bInsertedIntoTimeline)
  2715. {
  2716.     ulNumChildrenDursSet++;
  2717.     // /Don't set the child's duration unless the new duration
  2718.     // is less than the child's existing duration; the SMIL
  2719.     // spec says that a parent element can not extend the
  2720.     // duration of a child; fixes PR 50572:
  2721.     if (pElement->m_pSourceElement  &&  ( (UINT32)-1 ==
  2722.     pElement->m_pSourceElement->m_ulDuration  ||
  2723.     pElement->m_pSourceElement->m_ulDuration >
  2724.     m_pSourceElement->m_ulDuration) )
  2725.     {
  2726.      pElement->setDuration(m_pSourceElement->m_ulDuration,
  2727. TRUE);
  2728.     }
  2729. }
  2730.     }
  2731. }
  2732.     }
  2733.     // Check our children's fill behavior
  2734.     checkChildrenFillBehavior();
  2735.     //[SMIL 1.0 Compliance] Helps fix PR 14420 and 23025:
  2736.     // if a source has event-based timing based on this seq's
  2737.     // begin time (delay) then we need to notify that source
  2738.     // that we've resolved this value:
  2739.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  2740. }
  2741. /***************************************************************************/
  2742. /*
  2743.  * CSmilTimelinePar methods
  2744.  */
  2745. CSmilTimelinePar::CSmilTimelinePar(CSmilElement* pSourceElement,
  2746.    CSmilParser* pParser):
  2747.     CSmilTimelineElement(pSourceElement, pParser),
  2748.     m_nDurationAdded(0),
  2749.     m_ulFirstDuration(0),
  2750.     m_bFirstDurationHasBeenSet(FALSE),
  2751.     m_ulLastDuration(0)
  2752. {
  2753. }
  2754. CSmilTimelinePar::~CSmilTimelinePar()
  2755. {
  2756. }
  2757. void 
  2758. CSmilTimelinePar::setDelay(UINT32 ulDelay,
  2759.    // /NOTE: we ignore this in time containers that aren't media:
  2760.    BOOL bSetByParent)
  2761. {
  2762. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
  2763.     {
  2764. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
  2765. ADDDURATION_DEBUGOUT_STR_NEW_FILE :
  2766. ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
  2767. ::fprintf(f1, "CSmilTimelinePar{%s}::setDelay(delay=%lu, "
  2768. "bSetByParent=%sE) m_bDelaySet=%sE, beginOffset=%lun",
  2769. (const char*)m_pID, ulDelay,
  2770. bSetByParent?"TRU":"FALS",
  2771. m_bDelaySet?"TRU":"FALS", m_pSourceElement->m_lBeginOffset);
  2772. ::fclose(f1);
  2773. bFirstTimeAddDurDebugout = FALSE;
  2774.     }
  2775. #endif
  2776.     if(m_pSourceElement->m_bBeginOffsetSet)
  2777.     {
  2778. m_pSourceElement->m_ulDelay = (
  2779. ((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
  2780. (UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
  2781.     }
  2782.     else
  2783.     {
  2784. m_pSourceElement->m_ulDelay = ulDelay;
  2785.     }
  2786.     if (!m_bDelayEvent) //[SMIL 1.0 compliance] helps fix PR 14420.
  2787.     {
  2788. m_bDelaySet = TRUE;
  2789. ULONG32 ulNumChildrenWithNonEventBasedBegins = 0;
  2790. if(m_pChildren)
  2791. {
  2792.     CHXSimpleList::Iterator i = m_pChildren->Begin();
  2793.     for(; i != m_pChildren->End(); ++i)
  2794.     {
  2795. CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2796. pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
  2797. if (pElement->m_pSourceElement  &&  pElement->m_pSourceElement->
  2798. m_bHasAtLeastOneNonEventBasedBegin)
  2799. {
  2800.     ulNumChildrenWithNonEventBasedBegins++;
  2801. }
  2802.     }
  2803. }
  2804. // /Fixes PR 24046 (SMIL 2+ par version): if there are no children,
  2805. // then the par's duration is zero, so set it to 0:
  2806. if ((!m_pChildren  &&  m_pSourceElement->m_ulDuration == (UINT32)-1)  ||
  2807. 0 == ulNumChildrenWithNonEventBasedBegins)
  2808. {
  2809.     // /Checking 1st for explicit end or dur re-fixes PR 57150(par)
  2810.     // which was broken by fix for PR 24046 (note: PR 57150 has dur=x
  2811.     // *and* endsync="all" which is a strange thing to author):
  2812.     if (!m_pSourceElement->m_bHasExplicitDur  &&
  2813.     !m_pSourceElement->m_bHasExplicitEnd)
  2814.     {
  2815. m_pSourceElement->m_ulDuration = 0;
  2816.     }
  2817.     // /Helps fix PR 62688(par version): if all children are
  2818.     // event-begun and there is at least one child, and endsycn="all",
  2819.     // then we have an indefinite duration until all child ends resolve:
  2820.     if (m_pChildren  &&  SMILEventSourceAll ==
  2821.     m_pSourceElement->m_nEndsyncEventSourceTag  &&
  2822.     // /Ignore endsync if it has explicit end or dur:
  2823.     !m_pSourceElement->m_bHasExplicitDur  &&
  2824.     !m_pSourceElement->m_bHasExplicitEnd)
  2825.     {
  2826. m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
  2827.     }
  2828. }
  2829. if (m_pSourceElement->m_ulDuration != (UINT32)-1)
  2830. {
  2831.     setDuration(m_pSourceElement->m_ulDuration);
  2832. #if 0 //20011024-0
  2833.     // /Fixes PR 61174(version1) and par version of PR 56686
  2834.     // (version1): we know our duration already, so let's declare it
  2835.     // resolved so we get added to our parent (in case none of our
  2836.     // children have scheduled begin times in which case our
  2837.     // ::addDuration() would not get called up front and the overall
  2838.     // presentation would not include our duration at first):
  2839.     if (m_pSourceElement->m_bHasExplicitDur  ||
  2840.     m_pSourceElement->m_bHasExplicitEnd  ||
  2841.     // /For PR 62688(par version) and other endsync="all" bugs:
  2842.     SMILEventSourceAll ==
  2843.     m_pSourceElement->m_nEndsyncEventSourceTag)
  2844.     {
  2845. // /Be sure not to override a shorter duration that may have
  2846. // been imposed on us by our parent:
  2847. if (!m_bDurationSet  ||
  2848. !m_pSourceElement->m_bAddDurationAlreadyDone)
  2849. {
  2850.     HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  2851.     durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  2852. }
  2853. HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
  2854.     }
  2855. #else /* At least fix it for endsync="all":*/
  2856.     // /Fixes PR 61174(version1) and par version of PR 56686
  2857.     // (version1): we know our duration already, so let's declare it
  2858.     // resolved so we get added to our parent (in case none of our
  2859.     // children have scheduled begin times in which case our
  2860.     // ::addDuration() would not get called up front and the overall
  2861.     // presentation would not include our duration at first):
  2862.     if ((!m_pSourceElement->m_bHasExplicitDur  &&
  2863.     !m_pSourceElement->m_bHasExplicitEnd)  &&
  2864.     // /For PR 62688(par version) and other endsync="all" bugs:
  2865.     SMILEventSourceAll ==
  2866.     m_pSourceElement->m_nEndsyncEventSourceTag)
  2867.     {
  2868. // /Be sure not to override a shorter duration that may have
  2869. // been imposed on us by our parent:
  2870. if (!m_bDurationSet  ||
  2871. !m_pSourceElement->m_bAddDurationAlreadyDone)
  2872. {
  2873.     HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
  2874.     HX_ASSERT(m_pSourceElement->m_ulDuration ==
  2875.     m_pSourceElement->getPureDuration());
  2876.     durationResolved(m_pSourceElement->m_ulDuration, FALSE);
  2877. }
  2878. HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
  2879.     }
  2880. #endif
  2881. }
  2882.     }
  2883.     else //[SMIL 1.0 compliance] for PR 14420:
  2884. // let's not claim that the delay is set when we still
  2885. // are awaiting a delay (begin) event; we *do* need to
  2886. // add the delay of this to the event's begin offset.
  2887. // This is done by setting the new "m_bNonEventDelaySet"
  2888. // variable to TRUE and leaving m_bDelaySet to FALSE
  2889. // until the ElementResolved() call sets it to true:
  2890.     {
  2891. //Parent calls setDelay before we get to ElementResolved,
  2892. // thus m_bDelaySet should never be TRUE if we have a
  2893. // delay event:
  2894. HX_ASSERT(!m_bDelaySet);
  2895. m_bNonEventDelaySet = TRUE; //ElementResolved will look at this.
  2896. m_ulNonEventDelay = ulDelay;
  2897.     }
  2898.     
  2899.     if(m_pDependent  &&  m_bDurationSet)
  2900.     {
  2901. adjustDependentDuration(m_pDependent);
  2902. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2903. ULONG32 ulTotalDelay = 0;
  2904. if (HXR_OK !=
  2905. m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
  2906. {
  2907.     goto doneSettingDependent;
  2908. }
  2909. #else
  2910. ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
  2911. m_pSourceElement->m_ulDuration;
  2912. // /Helps fix PR 6XXXX(par version): if delay is already packed
  2913. // into the duration, then don't count it twice (as can happen in
  2914. // <seq><par begin="1s">...</par><par begin="1s" ...):
  2915. if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
  2916. {
  2917.     HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
  2918. /*OK[]*/     if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
  2919.     {
  2920. HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2921. ulTotalDelay);
  2922. if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
  2923. ulTotalDelay)
  2924. {
  2925.     ulTotalDelay -=
  2926.     m_pSourceElement->m_ulBeginOffsetFromSyncBase;
  2927. }
  2928.     }
  2929. }
  2930. #endif
  2931. if (WAY_IN_THE_FUTURE < ulTotalDelay)
  2932. {
  2933.     HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
  2934.     ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
  2935. }
  2936. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
  2937.     FILE* f1 = ::fopen("c:\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
  2938.     ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
  2939.     ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
  2940.     ::fprintf(f1, "nt%s:CSmilTimelinePar::setDelay(%lu): to %lu;"
  2941.     "tsetting dependent (%s)'s delay to %lun", (const char*)m_pID,
  2942.     ulDelay, m_pSourceElement->m_ulDelay,
  2943.     (const char*)m_pDependent->m_pID, ulTotalDelay);
  2944.     ::fclose(f1); 
  2945.     bFirstTimeAddDurDebugout = FALSE; 
  2946. #endif 
  2947.  
  2948. // /XXXEH- TODO: figure out if we need to claim this is being set by
  2949. // "parent" (which is really time base) so clip-begin-like action can
  2950. // occur; I don't think so, however:
  2951. m_pDependent->setDelay(ulTotalDelay, FALSE);
  2952.     }
  2953. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  2954. doneSettingDependent:
  2955. #endif
  2956.     //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025:
  2957.     m_pParser->m_pTimelineElementManager->notify(m_pID);
  2958. }
  2959. void
  2960. CSmilTimelinePar::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
  2961.   BOOL bDurationExtendingDueToPause)
  2962. {
  2963.     if (bDurationExtendingDueToPause)
  2964.     {
  2965. // /Need to handle this case:
  2966. HX_ASSERT(!bDurationExtendingDueToPause);
  2967.     }
  2968.     setParExclDuration(ulDuration, bSetFromParent);
  2969. }
  2970. void
  2971. CSmilTimelinePar::setMaxDuration(UINT32 ulMaxDuration)
  2972. {
  2973.     setParExclMaxDuration(ulMaxDuration);
  2974. }
  2975. void 
  2976. CSmilTimelinePar::resetDelay(UINT32 ulDelay)
  2977. {
  2978.     INT32 lAdjustedDelay = 0;
  2979.     UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;
  2980.     if(m_pSourceElement->m_bBeginOffsetSet)
  2981.     {
  2982. lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
  2983. m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
  2984.     }
  2985.     else
  2986.     {
  2987. m_pSourceElement->m_ulDelay = ulDelay;
  2988.     }
  2989.     if(m_pChildren)
  2990.     {
  2991. CHXSimpleList::Iterator i = m_pChildren->Begin();
  2992. for(; i != m_pChildren->End(); ++i)
  2993. {
  2994.     CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
  2995.     pElement->resetDelay(m_pSourceElement->m_ulDelay);
  2996. }
  2997.     }
  2998.     // /To fix PR 59851, we need to update our next-in-seq (m_pDependent) as
  2999.     // well as make sure sync-arc listeners know we've changed our overall
  3000.     // time bounds delay as well;
  3001.     if (m_pDependent && m_bDurationSet  &&
  3002.     ulPriorDelay != m_pSourceElement->m_ulDelay)
  3003.     {
  3004. #if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
  3005. ULONG32 ulTotalDelay = 0;
  3006.         if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&