smltime.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:229k
源码类别:

Symbian

开发平台:

C/C++

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