/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: smltime.cpp,v 1.3.4.2 2004/07/13 23:02:47 ehodge Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

// system
#include <time.h>
// include
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxxml.h"
#include "smiltype.h"
// pncont
#include "hxslist.h"
#include "hxmap.h"
// pnmisc
#include "hxwinver.h"
// rnxmllib
#include "hxxmlprs.h"
// rmasmil
#include "smlelem.h"
#include "smlparse.h"
#include "smltime.h"
#include "smlprstime.h"
// pndebug
#include "debugout.h"
#include "hxassert.h"
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE		
static const char HX_THIS_FILE[] = __FILE__;
#endif

// /#define XXXEH_DEBUGOUT_ADDDURATION
#if defined(XXXEH_DEBUGOUT_ADDDURATION)
#define ADDDURATION_DEBUGOUT_STR_NEW_FILE   "w"
#define ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE   "a+"
static BOOL bFirstTimeAddDurDebugout = TRUE;
#endif

/*
 * CSmilTimelineElementManager methods
 */

CSmilTimelineElementManager::CSmilTimelineElementManager():
    m_pElementMap(NULL),
    m_pNotifierMap(NULL)
{
}

CSmilTimelineElementManager::~CSmilTimelineElementManager()
{
    HX_DELETE(m_pElementMap);
    if(m_pNotifierMap)
    {
	CHXMapStringToOb::Iterator i = m_pNotifierMap->Begin();
	for(; i != m_pNotifierMap->End(); ++i)
	{
	    CHXSimpleList* pList = (CHXSimpleList*)(*i);
	    delete pList;
	}
	HX_DELETE(m_pNotifierMap);
    }
}

void
CSmilTimelineElementManager::addTimelineElement(CSmilTimelineElement* pElement)
{
    if(!m_pElementMap)
    {
	m_pElementMap = new CHXMapStringToOb;
    }
    (*m_pElementMap)[pElement->m_pID] = pElement;
}

CSmilTimelineElement*
CSmilTimelineElementManager::getTimelineElement(const char* pID)
{
    CSmilTimelineElement* pElement = NULL;
    if(m_pElementMap)
    {
	m_pElementMap->Lookup(pID, (void*&)pElement);
    }
    return pElement;
}

void
CSmilTimelineElementManager::addNotification(const char* pID,
					     CSmilTimelineElement* pElement)
{
    if(!m_pNotifierMap)
    {
	m_pNotifierMap = new CHXMapStringToOb;
    }

    CHXSimpleList* pNotifyList = NULL;
    if(!m_pNotifierMap->Lookup(pID, (void*&)pNotifyList))
    {
	pNotifyList = new CHXSimpleList;
	(*m_pNotifierMap)[pID] = pNotifyList;
    }
    pNotifyList->AddTail(pElement);
}

void
CSmilTimelineElementManager::notify(const char* pID)
{
    CHXSimpleList* pNotifyList = NULL;
    if(m_pNotifierMap)
    {
	if(m_pNotifierMap->Lookup(pID, (void*&)pNotifyList))
	{
	    CSmilTimelineElement* pDependentElement = NULL;
	    if(m_pElementMap->Lookup(pID, (void*&)pDependentElement))
	    {
		CHXSimpleList::Iterator i = pNotifyList->Begin();
		for(; i != pNotifyList->End(); ++i)
		{
		    CSmilTimelineElement* pElement = 
			(CSmilTimelineElement*)(*i);
		    pElement->elementResolved(pDependentElement);
		}
	    }
	}
    }
}

void
CSmilTimelineElementManager::resetTimeline()
{
    if(m_pElementMap)
    {
	CHXMapStringToOb::Iterator i = m_pElementMap->Begin();
	for(; i != m_pElementMap->End(); ++i)
	{
	    CSmilTimelineElement* pElement = 
		(CSmilTimelineElement*)(*i);
	    pElement->reset();
	}
    }
}	
/*
 * CSmilTimelineElement methods
 */

CSmilTimelineElement::CSmilTimelineElement(CSmilElement* pSourceElement,
					   CSmilParser* pParser):
    m_pSourceElement(pSourceElement),
    m_pParser(pParser),
    m_bDurationSet(FALSE),
    m_bMaxDurationSet(FALSE),
    m_bDelaySet(FALSE),
    m_bDontResetDuration(FALSE),
    m_bNonEventDelaySet(FALSE),
    m_ulNonEventDelay((UINT32)-1),
    m_bDelayEvent(FALSE),
    m_bDurationEvent(FALSE),
    m_pChildDurAddedMap(NULL),
    m_bHasChildWithScheduledBegin(FALSE),
    m_bInElementResolved(FALSE),
    m_pParent(NULL),
    m_pChildren(NULL),
    m_pDependent(NULL)
{
    m_pID = new char[pSourceElement->m_pNode->m_id.GetLength() + 1];
    strcpy(m_pID, (const char*)m_pSourceElement->m_pNode->m_id); /* Flawfinder: ignore */

    //[SMIL 1.0 Compliance] Helps fix PR 26471:
    // /XXXEH- TODO: this is probably one of the places where
    // endsync="media" is handled.  We probably don't want to do the
    // following if() statement if endsync is NOT media on the parent
    // of an anchor|area element:
    if (SMILAnchor != m_pSourceElement->m_pNode->m_tag  &&
	    SMILArea != m_pSourceElement->m_pNode->m_tag)
    {
	m_pParser->m_pTimelineElementManager->addTimelineElement(this);
    }

    if(pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin ||
	pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd ||
	pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)
    {
	m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_BeginEventSourceID,
	    this);
	// /If we've already got a resolved begin, then we don't want to claim
	// that we're awaiting this sync-arc begin (as can happen if
	// begin="0s; x.begin+4s")
	if (!pSourceElement->m_bBeginOffsetSet)
	{
	    m_bDelayEvent = TRUE;
	}
    }

    if(pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin ||
	pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd ||
	pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)
    {
	m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_EndEventSourceID,
	    this);
	// /If we've already got a resolved end, then we don't want to claim
	// that we're awaiting this sync-arc end (as can happen if
	// end="10s; x.begin+14s")
	if (!pSourceElement->m_bEndOffsetSet)
	{
	    m_bDurationEvent = TRUE;
	}
    }

    if(pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
    {
	m_pParser->m_pTimelineElementManager->addNotification(pSourceElement->m_EndsyncEventSourceID,
	    this);
	m_bDurationEvent = TRUE;
    }

    m_pChildDurAddedMap = new CHXMapStringToOb();

    // /XXXEH- TODO: make sure this is what we want to do:
    // /Get next resolved time, if any.  If none are found in a non-empty
    // begin-time list, then treat this as a delayed event:
    if (NULL != pSourceElement->m_pBeginTimeList  &&
	    !pSourceElement->m_pBeginTimeList->IsEmpty())
    {
	SmilTimeValue* pNextResolvedTimeValue = NULL;

	HX_RESULT rettimeval = HXR_OK;
	rettimeval = pSourceElement->getNextResolvedTimeValue(
		pNextResolvedTimeValue,
		// /XXXEH- TODO: make sure we don't want to input cur time here;
		// is it possible that we'd get here after time 0 in the parent
		// timeline???  I don't think so...:
		SMILTIME_NEGATIVE_INFINITY,
		SMILTIME_NEGATIVE_INFINITY,
		SmilBeginTimeList,
		/* Don't need list of resolved times:*/ NULL);
	if (!SUCCEEDED(rettimeval)  ||  NULL == pNextResolvedTimeValue)
	{
	    // /Has no resolved time yet so must be awaiting an event:
	    m_bDelayEvent = TRUE;
	}
    }
}

CSmilTimelineElement::~CSmilTimelineElement()
{
    delete m_pChildren;
    delete[] m_pID;
    HX_DELETE(m_pChildDurAddedMap);
}

void
CSmilTimelineElement::reset()
{
    m_bDelaySet = FALSE;
    m_bNonEventDelaySet = FALSE;
    m_ulNonEventDelay = (UINT32)-1;
    m_bDurationSet = FALSE;
    m_bMaxDurationSet = FALSE;
    // /XXXEH- do we really want to do this? Find a way to test this:
#if defined(XXXEH_NEEDS_TESTING)
    HX_DELETE(m_pChildDurAddedMap); // /start fresh
#endif
}

void
CSmilTimelineElement::prepForRestart()
{
    m_bDelaySet = FALSE;
    m_bNonEventDelaySet = FALSE;
    m_ulNonEventDelay = (UINT32)-1;

#if XXXEH_OLD_WAY_THAT_DIDNT_LET_SETDURATION_TAKE_CARE_OF_NEW_DUR
    if (((UINT32)-1) != m_pSourceElement->m_ulOriginalDuration)
    {
	resetDuration(m_pSourceElement->m_ulOriginalDuration);
    }
    // /Note: leave m_bDurationSet & m_bMaxDurationSet alone for restart
#else
    //...But if we're restarting, our duration may be different and this
    // gets handled in CSmilTimelineElement::setDuration():
    m_bDurationSet = FALSE;
    // /Fixes PR 54704: if we don't reset this in concert with resetting
    // m_bDurationSet, above, then ancestorEventsAreResolved() will fail
    // when a re-insertTimelineElement() call on this occurs:
    m_bDurationEvent = FALSE;
#endif

}


void 
CSmilTimelineElement::setDelay(UINT32 ulDelay, BOOL bSetByParent)
{
    ULONG32 ulPreviouslySetDelay = m_pSourceElement->m_ulDelay;
    ULONG32 ulPreviouslySetPureDuration = m_pSourceElement->getPureDuration();

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineElement{%s}::setDelay(delay=%lu, "
		"bSetByParent=%sE), prior delay=%lu, m_bDelaySet=%sE\n",
		(const char*)m_pID, ulDelay,
		bSetByParent?"TRU":"FALS",
		ulPreviouslySetDelay,
		m_bDelaySet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    if(!m_bDelaySet)
    {
	// /For PR 59584: if we're just resolving this to let the
	// group duration "resolve" to unresolved, don't count begin:
	if(WAY_IN_THE_FUTURE <= ulDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE >= ulDelay);
	}
	else if(!m_bDelayEvent)
	{
	    BOOL bDelayClippedDueToNegOffset = FALSE;
	    if(m_pSourceElement->m_bBeginOffsetSet)
	    {
		m_pSourceElement->m_ulDelay = ulDelay;

		// /Handle all cases so that we don't overflow:
		UINT32 ulPosOffset = m_pSourceElement->m_lBeginOffset > 0?
			m_pSourceElement->m_lBeginOffset : 0;
		UINT32 ulNegOffset = m_pSourceElement->m_lBeginOffset < 0?
			(UINT32)(-m_pSourceElement->m_lBeginOffset) : 0;
		UINT32 ulClippedAmt = 0;

		if (ulNegOffset > 0)
		{
		    m_pSourceElement->m_bNegBeginOffsetAlreadyUsed =
			    TRUE;
		}

		m_pSourceElement->m_ulDelay += ulPosOffset;
		if (m_pSourceElement->m_ulDelay >= ulNegOffset)
		{
		    m_pSourceElement->m_ulDelay -= ulNegOffset;
		}
		else
		{
		    // /If set by parent, then we want to use the entire
		    // negative offset FROM OUR PARENT's BEGIN which already
		    // has the delay in it, so <par begin="2s"><ref begin=
		    // "-3s" ...> would begin the ref at 2s w/3s clip-begin:
		    ulClippedAmt = bSetByParent? ulNegOffset : ulNegOffset -
			    m_pSourceElement->m_ulDelay;
		    // /If clip-begin is invalid, set it otherwise add to it:
		    m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
			    m_pSourceElement->m_ulAuthoredClipBegin?
			    ulClippedAmt : ulClippedAmt +
			    m_pSourceElement->m_ulAuthoredClipBegin);
		    if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
		    {
			if (m_pSourceElement->m_ulDuration > ulClippedAmt)
			{
			    m_pSourceElement->m_ulDuration -= ulClippedAmt;
			}
			// /else duration is negative; it can't ever play.
			else
			{
			    m_pSourceElement->m_ulDuration = 0;
			}
		    }
		}
	    }
	    // /Fixes most of PR64499: when restarting the parent of a
	    // long-sync-arc-begun element, the begin should still be based on
	    // the long sync-arc's global time:
	    else if ((UINT32)-1 != m_pSourceElement->m_ulLongSyncArcBeginInGroupTime
		    &&  m_pSourceElement->m_bIsRestarting)
	    {
		SMILNode* pSyncNode = !m_pParser? NULL :
		       m_pParser->getSyncAncestor(m_pSourceElement->m_pNode);
		HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
		if (pSyncNode  &&  pSyncNode->m_pElement->m_bIsRestarting)
		{		
		    m_pSourceElement->m_ulDelay =
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime;
		}
	    }
	    // /Else we've established that the beginOffset is not set, so
	    // just use the delay:
	    else
	    {
		m_pSourceElement->m_ulDelay = ulDelay;

		// /Fixes PR 71386 and PR 77406: event-based begins with sync-
		// arc ends (that are already resolved, here) should not
		// include the delay twice; use the *end* not the *duration*:
		if (m_pSourceElement->m_bEndOffsetSet  &&
			// /Fixes PR 8XYXZ (broken by original PR 71386 fix);
			// If being set by parent, we don't need to do anything
			// because delay is parent delay, not explicitly-set
			// begin val:
			!bSetByParent)
		{
		    // /If dur was explicitly authored along with end, use the
		    // min(end, dur+delay):
		    if (WAY_IN_THE_FUTURE ==
			    m_pSourceElement->m_ulAuthoredDur  ||
			    (UINT32)-1 == m_pSourceElement->m_ulAuthoredDur  ||
			    // /Fixes PR 71386 Part 3 = version where element
			    // has end="x.end" AND has dur="z"; if z+delay >
			    // x.end, ignore dur:
			    (m_pSourceElement->m_ulAuthoredDur +
			    m_pSourceElement->m_ulDelay >
			    m_pSourceElement->m_lEndOffset))
		    {
			if (m_pSourceElement->m_lEndOffset > 0  &&
				(ULONG32)m_pSourceElement->m_lEndOffset >=
				m_pSourceElement->m_ulDelay)
			{
			    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
				    FALSE;
			    m_pSourceElement->m_ulDuration =
				    m_pSourceElement->m_lEndOffset -
				    m_pSourceElement->m_ulDelay;
			}
			else
			{
			    HX_ASSERT(0  &&  "pleaseContact_ehodge!");
			    m_pSourceElement->m_ulDuration = 0;
			}
		    }
		}
	    }
	    m_bDelaySet = TRUE;
	    if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
	    {
		m_pParser->insertTimelineElement(m_pID, 
		    m_pSourceElement->m_ulDelay);
	    }
            // XXXMEH - animation can be children of media elements, so when
            // a media element gets its delay set, then we need to
            // set the delay of any children
	    if(m_pChildren)
	    {
                LISTPOSITION pos = m_pChildren->GetHeadPosition();
                while (pos)
                {
                    CSmilTimelineElement* pChildElement =
                        (CSmilTimelineElement*) m_pChildren->GetNext(pos);
                    if (pChildElement)
                    {
                        pChildElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
                    }

                }
	    }
	}
    }
    else
    {
	HX_ASSERT(WAY_IN_THE_FUTURE > ulDelay); // /PR 59584-related check.

	if(m_pSourceElement->m_bBeginOffsetSet)
	{
	    m_pSourceElement->m_ulDelay = (
		((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
		(UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
	}
	else
	{
	    // /There are two cases where we might arrive here with
	    // ulDelay not equalling ulPreviouslySetDelay; one is when the
	    // original delay is based on a sync-arc to an element that never
	    // gets added to the timeline, and the other is when the original
	    // delay is based on a long sync-arc.  The following allows both
	    // to work; we don't want to use the new delay if the orig one
	    // was greater than the new one, otherwise we'll play it too soon
	    // and that happens in SMIL2 Timing interop case 1.15:
	    if (!bSetByParent  ||  ulDelay > ulPreviouslySetDelay)
	    {
		m_pSourceElement->m_ulDelay = ulDelay;
	    }
	}

	// /If we've got a long sync-arc begin delay that is earlier (and
	// also resolved earlier) than our parent's begin delay, then we want
	// to do a clip-begin of the difference, e.g,:
	//   <par begin="3s">
	//     <video begin="someElementBeginningAtTimeZero.begin" .../> ...
	// so the video element should begin at 3s and clip the 1st 3s of it.
	if (bSetByParent  &&
		ulPreviouslySetDelay < m_pSourceElement->m_ulDelay)
	{
	    LONG32 lDiff = m_pSourceElement->m_ulDelay -ulPreviouslySetDelay;
	    HX_ASSERT(lDiff >= 0);
	    ULONG32 ulDiff = (ULONG32)lDiff;
	    // /If clip-begin is invalid, set it otherwise add to it:
	    m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
		    m_pSourceElement->m_ulAuthoredClipBegin?
		    ulDiff : ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
	    if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
	    {
		if (m_pSourceElement->m_ulDuration > ulDiff)
		{
		    m_pSourceElement->m_ulDuration -= ulDiff;
		}
		else
		{
		    m_pSourceElement->m_ulDuration = 0;
		}

		if (m_pSourceElement->m_pNode)
		{
		    m_pParser->resetTimelineElementDuration(
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->getPureDuration(),
			    ulPreviouslySetPureDuration);
		    m_pParser->m_pTimelineElementManager->notify(
			    (const char*)m_pSourceElement->m_pNode->m_id);
		}
	    }
	}
	// /More for PR 50411: if it wasn't inserted yet, do so:
	// /(Also helps fix other long-sync-arc bugs like PR 64498 & PR 64499):
	if (m_pSourceElement->m_bAwaitingSyncAncestorBeginNotification)
	{
	    HX_ASSERT(!m_pSourceElement->m_bInsertedIntoTimeline);
	    m_pParser->insertTimelineElement(m_pID,
		    m_pSourceElement->m_ulDelay);
	    m_pSourceElement->m_bAwaitingSyncAncestorBeginNotification =
		    FALSE;
	}
    }

    // /This helps fix PR 50588 (and other sync-arc-to-x's-begin-where-x-has-
    // resolved-delay-but-not-resolved-duration bugs); notify sync-arc
    // dependents if our delay (or duration) was set or changed:
    if (ulPreviouslySetDelay != m_pSourceElement->m_ulDelay  ||
	    ulPreviouslySetPureDuration != m_pSourceElement->getPureDuration())
    {
	m_pParser->m_pTimelineElementManager->notify(m_pID);
    }
}

void 
CSmilTimelineElement::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
				  BOOL bDurationExtendingDueToPause)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineElement{%s}::setDuration(ulDuration=%lu, "
		"bSetFromParent=%sE) m_pSourceElement->m_ulDelay=%lu, m_bDelaySet=%s\n",
		(const char*)m_pID, ulDuration,
		bSetFromParent?"TRU":"FALS", m_pSourceElement->m_ulDelay,
		m_bDelaySet?"TRUE":"FALSE-#############!!! DUDE!");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    BOOL bTrackStartsTooLateSoTrackRemoved = FALSE;

    ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

    if(bSetFromParent)
    {
	BOOL bOKToOverrideDuration = FALSE;
	if ((UINT32)-1 == m_pSourceElement->m_ulAuthoredDur)
	{
	    if (!m_pSourceElement->m_bHasExplicitEnd  ||  !m_bDurationSet)
	    {
		bOKToOverrideDuration = TRUE;
	    }
	}
	else if (m_pSourceElement->m_ulAuthoredDur == WAY_IN_THE_FUTURE  &&
		m_pSourceElement->m_bHasExplicitEnd  &&  m_bDurationSet  &&
		// /Fixes PR 50676 part 5: if m_bDurationSet but duration was
		// not set to anything but unresolved, then we do want to
		// override the unresolved value; this continues to let the
		// fix work from 5/9/2001's addition of this else-if:
		m_pSourceElement->m_ulDuration != WAY_IN_THE_FUTURE)
	{
	    bOKToOverrideDuration = FALSE;
	}
	else if (m_pSourceElement->m_ulAuthoredDur >= ulDuration  &&
	    ((UINT32)-1 == m_pSourceElement->m_ulMaxActiveDur  ||
	    m_pSourceElement->m_ulMaxActiveDur >= ulDuration) )
	{
	    // /XXXEH- I need to find content that has this feature;
	    // I'm pretty sure I want to add m_ulBeginOffsetFromSyncBase to
	    // m_ulAuthoredDur when comparing with ulDuration, above, since
	    // ulDuration is in syncbase time coordinate system:
	    HX_ASSERT((!m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  ||
		    (m_pSourceElement->m_ulBeginOffsetFromSyncBase +
		    m_pSourceElement->m_ulAuthoredDur >= ulDuration) )  &&
		    "contact ehodge to fix");
	    bOKToOverrideDuration = TRUE;
	}

	// /If begin="5s" and end|dur|max are explicitly set, don't override
	// the duration (interop #1.1: BeginEndEvents_Case1.smi):
	// /XXXEH- make sure delay is accounted for (if "ulDuration" is
	// really delay+dur):
	if (bOKToOverrideDuration)
	{
	    // /Fixes BUG-20001116_parDurExtended_due_to_syncArc_delay.smi:
	    ULONG32 ulRevisedDur = ulDuration;

	    BOOL bOkToSetDuration = TRUE;

	    BOOL bOKToResetDurationIncludesDelayVar = TRUE;

	    BOOL bRevisedDurDoesNotIncludeDelayBeyondSyncbase = FALSE;

	    // /Note: when we say "parent" in this function, we really
	    // mean sync ancestor (e.g., par when switch is our parent and
	    // par is parent of switch).

	    ULONG32 ulSyncBaseDelay = (UINT32)-1;
	    SMILNode* pSyncNode = !m_pParser? NULL :
		   m_pParser->getSyncAncestor(m_pSourceElement->m_pNode);
	    HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
	    if (pSyncNode  &&  pSyncNode->m_pElement)
	    {
		ulSyncBaseDelay = pSyncNode->m_pElement->m_ulDelay;
		// /XXXEH- in PR 59584 (which works OK with code as-is),
		// syncNode is a Seq but prior sibling should really be
		// treated as the "sync base", not the seq.  There are 3
		// other places in this file where this code is needed,
		// but need content that's broken by this before I fix it: PR 6XXX5:
		if (pSyncNode->m_tag == SMILSeq)
		{
		    ulSyncBaseDelay = m_pParser->
			    getSyncBaseTimeInGroupTimeCoords(
			    m_pSourceElement->m_pNode);
		}
	    }

	    // /We need to make sure that our begin+duration does not exceed
	    // our parent's end; the ulDuration begin passed in is our
	    // syncBase-imposed duration that already includes our syncBase's
	    // delay but does not take into account our begin offset or
	    // delay relative to our syncBase's begin.  To adjust for this,
	    // set the new duration to ulDuration minus (beginOffset set?
	    // beginOffset : (delay-parentDelay):  Note that we can have a
	    // delay that is due to a sync-arc and not due to our syncBase's
	    // delay and thus we may not have a beginOffset set but we still
	    // may begin later than our syncBase:
	    if (m_pSourceElement->m_bBeginOffsetSet)
	    {
		// /Include this code because it fixes
		// <par dur="5s" begin="1s"><ref begin="2s"/></par>
		// as in BUG-20001116_parDurExtended_due_to_syncArc_delay.smi
		// (which broke again due to fix for PR 53514, below, I think):
		if (m_pSourceElement->m_lBeginOffset > 0)
		{
		    ulRevisedDur=((ULONG32)m_pSourceElement->m_lBeginOffset>=
			    ulRevisedDur)? 0 : (ulRevisedDur -
			    (ULONG32)m_pSourceElement->m_lBeginOffset);
		    bRevisedDurDoesNotIncludeDelayBeyondSyncbase = TRUE;


		    // /Fixes PR 58568: if revised dur is 0 or negative
		    // (ULONG32 floor of 0 prevents it from being negative),
		    // then we need to remove the track if it's been added
		    // already, otherwise it'll play in spite of it's
		    // parent ending before that time:
		    if (0 == ulRevisedDur)
		    {
			if (m_pSourceElement->m_pHandler  &&
				m_pSourceElement->m_bInsertedIntoTimeline)
			{
			    // /The following signals subsequent timeline
			    // adjustments to ignore this element in parent
			    // duration computations:
			    m_pSourceElement->m_bCurEndClippedByParent = TRUE;
			    HX_RESULT retval2 = m_pSourceElement->m_pHandler->
				    handleTrackRemoval((const char*)m_pID,
				    (INT32)m_pSourceElement->m_pNode->m_nGroup);
			    if (HXR_OK == retval2)
			    {
				// /XXXEH- verify in SMIL 2.0 spec how to
				// handle syncArcs to element that's beyond
				// its syncBase and thus won't start:
				// /Fixes case where element has sync arc
				// to this end time and we need to notify it
				// that we've ended early:
				m_pParser->m_pTimelineElementManager->notify((const char*)m_pID);
				bTrackStartsTooLateSoTrackRemoved = TRUE;
				goto cleanup;
			    }
			}
			
		    }
		}
	    }
	    else // /No begin offset, so use delay minus syncBase delay:
	    {
		if (pSyncNode  &&  pSyncNode->m_pElement)
		{
		    if ((UINT32)-1 != ulSyncBaseDelay  &&
			    (UINT32)-1 != m_pSourceElement->m_ulDelay )
		    {
			HX_ASSERT(m_pSourceElement->m_ulDelay >=
				ulSyncBaseDelay);
			if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay  ||
				// /Helps fix PR 66391: if delays are equal &
				// revisedDur=0, then remove this track:
				(0 == ulRevisedDur  &&
				m_pSourceElement->m_ulDelay == ulSyncBaseDelay))
			{
			    ULONG32 ulEffectiveBeginOffset =
				    m_pSourceElement->m_ulDelay -
				    ulSyncBaseDelay;
			    ulRevisedDur =
				    ulRevisedDur>ulEffectiveBeginOffset?
				    ulRevisedDur-ulEffectiveBeginOffset : 0;
			    bRevisedDurDoesNotIncludeDelayBeyondSyncbase = TRUE;

			    bOKToResetDurationIncludesDelayVar = FALSE;
			    // /Be sure to update the begin offset relative
			    // to the parent:  Helps fix
			    // "...20001116_parDurExtended_due_to_syncArc..."
			    m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase =
				    TRUE;
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase =
				    ulEffectiveBeginOffset;
			    // /Fixes part of PR 50684: if revised dur is 0
			    // or negative (ULONG32 floor of 0 prevents it
			    // from being negative), then we need to remove
			    // the track if it's been added already:
			    if (0 == ulRevisedDur  &&
				    m_pSourceElement->m_pHandler  &&
				    m_pSourceElement->m_bInsertedIntoTimeline)
			    {
				m_pSourceElement->m_bCurEndClippedByParent = TRUE;
				HX_RESULT retval2 = m_pSourceElement->m_pHandler->
					handleTrackRemoval((const char*)m_pID,
					(INT32)m_pSourceElement->m_pNode->m_nGroup);
				if (HXR_OK == retval2)
				{
				    // /Fixes case where element has sync arc
				    // to this end time and we need to notify it
				    // that we've ended early:
				    m_pParser->m_pTimelineElementManager->notify((const char*)m_pID);
				    bTrackStartsTooLateSoTrackRemoved = TRUE;
				    goto cleanup;
				}
			    }
			}
				
		    }
		    else if ((UINT32)-1 == ulSyncBaseDelay)
		    {
			// /Fixes case where par parent child of excl was
			// allowing child to begin even though par has no
			// explicit resolved begin and thus shouldn't begin:
			bOkToSetDuration = FALSE;
		    }
		}
	    }

	    if (bOkToSetDuration  &&  ((UINT32)-1 ==
		    m_pSourceElement->m_ulDuration  ||
		    m_pSourceElement->m_ulDuration < ulRevisedDur) )
	    {
		HX_ASSERT(m_pSourceElement->m_ulDuration == m_pSourceElement->getPureDuration());
		// /Adding this if() fixes PR 53514; parent explicit dur was
		// being forced on this child even if child has a shorter
		// intrinsic duration (which isn't known yet).  We need to
		// hold off setting the duration and rather set the max
		// duration:
		setMaxDuration(ulRevisedDur);
	    }
	    else if (bOkToSetDuration)
	    {
		m_bDurationSet = m_bDontResetDuration = TRUE;

		if (m_pSourceElement->m_ulDuration != ulRevisedDur)
		{
		    // /Parent-imposed duration always is relative to parent
		    // begin, so duration thus includes delay offset from
		    // parent.  Don't set flag unless offset>0, for
		    // consistency:
		    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
		    {
			m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
		    }
		    if (bRevisedDurDoesNotIncludeDelayBeyondSyncbase)
		    {
			m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = FALSE;
		    }

		    // /Adding this if() conditional around the call to
		    // "resetTimelineElement...()" makes PR55885 happen only
		    // after the first time it's played.  If you don't close
		    // the player and then restart the clip, sometimes 55885
		    // bug still appears; need to debug with core folks to
		    // see why this happens.
		    // /NOTE: Adding the following conditional *does* 100% fix
		    // "BUG-20010613-clickAllFourAndRestartOfGreenCauses..."
		    // "...ExtensionOfTimelinePastParEnd.smil":
		    if ((UINT32)-1 != m_pSourceElement->m_ulDelay)
		    {
			m_pParser->resetTimelineElementDuration(m_pID,
				// /Using the revised dur here helps fix
				// PR 59223, PR 50684, & PR 56795 (and
				// probably a lot of others):
				ulRevisedDur, ulPriorPureDuration);
		    }
		}
	    }
	}
	// /Fixes bug where par with a synchbase end (e.g., end="foo.begin")
	// was being ignored completely because its children were never
	// being added to the timeline:
	if (!m_pSourceElement->m_bInsertedIntoTimeline)
	{
	    if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
	    {
		// /Helps fix timing interop cases in the 11.2-11.9 range:
		if ((UINT32)-1 != m_pSourceElement->m_ulDelay)
		{
		    m_pParser->insertTimelineElement(m_pID, 
			    m_pSourceElement->m_ulDelay);
		}
	    }
	}
    }
    else // /Else this duration is not being set by parent:
    {
	if(!m_bDurationSet  ||
		// /Helps fix PR 86107; if pause is extending duration, we're
		// only here to notify our dependents and ancestor excl so it
		// can potentially update its duration so subSEQuent clips can
		// adjust their delays outward before getting scheduled w/core:
		bDurationExtendingDueToPause)
	{
	    LONG32 lDelayFromParentBegin = 0;
	    HX_ASSERT((!m_pSourceElement->m_bBeginOffsetSet  ||
		    m_pSourceElement->m_lBeginOffset>=0  ||
		    m_pSourceElement->m_bNegBeginOffsetAlreadyUsed)  &&
		    "ehodge_please_help_me_find_content_that_trips_this");
	    if (m_pSourceElement->m_bBeginOffsetSet  &&
		    // /Don't adjust if already adjusted for neg offset:
		    !m_pSourceElement->m_bNegBeginOffsetAlreadyUsed)
	    {
		lDelayFromParentBegin = m_pSourceElement->m_lBeginOffset;
	    }
	    // /Handle case where element began based on event or late-
	    // resolving time, in which case we want to treat the diff
	    // between when it resolved and what its sync-parent begin
	    // is as if it were a m_lBeginOffset:
	    else if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
	    {
		lDelayFromParentBegin = (LONG32)
			m_pSourceElement->m_ulBeginOffsetFromSyncBase;
	    }
	    if (lDelayFromParentBegin>0  &&
		    // /1st part of fix for interop case 1.15 where begin and
		    // end are explicitly set to same val so dur should be 0:
		    ulDuration != 0)
	    {
		m_pSourceElement->m_ulDuration = (
		    ((INT32)ulDuration + lDelayFromParentBegin >0) ?
		    (UINT32)(
		    (INT32)ulDuration + lDelayFromParentBegin) : 0);

		// /NOTE: m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase
		// is TRUE in PR 79699 (occasionally) but it plays as expected so
		// I removed the HX_ASSERT() on !(..->m_bDurationIncludesDelay...)].
// /XXXEH- 20020625: maybe don't do above adding of delay, and then set this to FALSE?:
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
		// /If duration is unresolved or indefinite, don't include
		// delay from parent so parent duration doesn't get extended
		// beyond WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == ulDuration)
		{
		    m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
		}
	    }
	    else
	    {
		lDelayFromParentBegin = 0; // /In case it was negative.
		m_pSourceElement->m_ulDuration = ulDuration;
		// /If end==begin, we need to NOT play the clip but we do
		// need to fire a beginEvent and endEvent for it.  However,
		// if end < begin, we don't fire these events (as in
		// SMIL 2.0 Interop Timing case 1.16):
		BOOL bEndBeforeBegin =
			m_pSourceElement->m_bBeginOffsetSet  &&
			m_pSourceElement->m_bEndOffsetSet  &&
			m_pSourceElement->m_lBeginOffset >
			m_pSourceElement->m_lEndOffset;
		if (0 == m_pSourceElement->m_ulDuration  &&
			!bEndBeforeBegin  &&  m_pSourceElement->m_pNode)
		{
		    // /Raise a beginEvent but don't play the thing (as in
		    // SMIL 2.0 Interop Timing case 1.15):
		    HX_RESULT rslt = HXR_OK;
		    rslt = m_pParser->tryToResolveBeginEndEvents(
			    "beginEvent",
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->m_ulDelay);
		    rslt = m_pParser->tryToResolveBeginEndEvents(
			    "endEvent",
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->m_ulDelay);
		}
	    }
	    m_bDurationSet = TRUE;

	    HX_ASSERT(m_pSourceElement->m_ulDuration>0  &&
		    "timing#1.15: child's dur (=0) not added to parent; refix!");
	    if(m_pParent  &&
		    // /Timing interop case 1.15 2nd part of fix:
		    m_pSourceElement->m_ulDuration>0)
	    {
		m_pParent->addDuration(m_pSourceElement->m_ulDuration,
			m_pSourceElement->m_ulDelay,
			(UINT32)lDelayFromParentBegin, m_pID);
		m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
	    }
	    // /Only do this if we're really setting the original duration
	    // (and not updating duration due to predicted pause extension):
	    if (!bDurationExtendingDueToPause)
	    {
		// /this keeps track of dur="x" or implicit source dur, in
		// case this element restarts after playing at least once:
		m_pSourceElement->m_ulOriginalDuration =
			m_pSourceElement->getPureDuration();
		HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
			m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
	    }
	}
	else if(!m_bDontResetDuration)
	{
	    m_pSourceElement->m_ulDuration = ulDuration;
	    m_pParser->resetTimelineElementDuration(m_pID,
		    m_pSourceElement->getPureDuration(),
		    ulPriorPureDuration);
	    // /this keeps track of dur="x" or implicit source dur, in
	    // case this element restarts after playing at least once:
	    m_pSourceElement->m_ulOriginalDuration =
		    m_pSourceElement->getPureDuration();
	    HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
	}
	// /Adding the following else-if fixes PR 52110: if parent explicit
	// dur sets this's duration but this never got added to parent (via
	// addDuration()), then all subSEQuent tracks won't ever get resolved
	// begins:
	else if(!m_pSourceElement->m_bAddDurationAlreadyDone)
	{
	    HX_ASSERT(m_bDurationSet); // /Here because this was already set.
	    HX_ASSERT(m_bDelaySet  &&  (UINT32)-1 != m_pSourceElement->m_ulDelay);
	    HX_ASSERT(m_pSourceElement->m_ulDuration>0  &&
		    "child's dur (=0) not added to parent; refix!");
	    if(m_pParent  &&  m_pSourceElement->m_ulDuration>0)
	    {
		ULONG32 ulDelayFromSyncBaseBegin = 0;
		if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
		{
		    ulDelayFromSyncBaseBegin =
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
		m_pParent->addDuration(m_pSourceElement->m_ulDuration, 
			m_pSourceElement->m_ulDelay,
			ulDelayFromSyncBaseBegin, m_pID);
		m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
	    }
	}

	// /If "dur" attribute value or intrinsic dur is less than the
	// min attribute value or greater than the max attribute value,
	// then we need to use min or max attribute's value as the duration:
	if (!m_bDontResetDuration  &&
		(m_pSourceElement->m_bUseMediaDurForMinDur  ||
		m_pSourceElement->m_bUseMediaDurForMaxDur  ||
		m_pSourceElement->m_ulMinActiveDur > 0  ||
		m_pSourceElement->m_ulMaxActiveDur != ((UINT32)-1) ) )
	{
	    BOOL bDoUpdate = FALSE;
	    LONG32 lBeginOffset = 0;
	    if (m_pSourceElement->m_bBeginOffsetSet)
	    {
		lBeginOffset = m_pSourceElement->m_lBeginOffset;
	    }
	    // /First, check if m_pSourceElement->m_bUseMediaDurForMinDur
	    // is TRUE.  If so, we want to use the max of ulDuration
	    // (media's intrinsic dur) and any explicitly-set dur (via
	    // dur="..." {or end="..."[-begin=".."]}:
	    if (m_pSourceElement->m_bUseMediaDurForMinDur)
	    {
		if (((UINT32)-1) != m_pSourceElement->m_ulAuthoredDur)
		{
		    HX_ASSERT(0 == m_pSourceElement->m_ulMinActiveDur);
		    // /Use authored dur if it's greater than intrinsic
		    // duration OR if max<min (since max<min negates both
		    // properties):
		    if (m_pSourceElement->m_ulAuthoredDur > ulDuration  ||
			    (((UINT32)-1) !=
			    m_pSourceElement->m_ulMaxActiveDur  &&
			    m_pSourceElement->m_ulMaxActiveDur < ulDuration))
		    {
			m_pSourceElement->m_ulDuration =
				m_pSourceElement->m_ulAuthoredDur;
			bDoUpdate = TRUE;
		    }
		}
	    }
	    // /Next, check if m_pSourceElement->m_bUseMediaDurForMaxDur
	    // is TRUE.  If so, we want to use the min of ulDuration
	    // (media's intrinsic dur) and any explicitly-set dur (via
	    // dur="..." or {end="..."[-begin=".."]}:
	    else if (m_pSourceElement->m_bUseMediaDurForMaxDur)
	    {
		if (((UINT32)-1) != m_pSourceElement->m_ulAuthoredDur)
		{
		    HX_ASSERT(((UINT32)-1) ==
			    m_pSourceElement->m_ulMaxActiveDur);
		    // /Use authored dur if it's less than intrinsic
		    // duration OR if min>max (since min>max negates both
		    // properties):
		    if (m_pSourceElement->m_ulAuthoredDur < ulDuration  ||
			    (0 != m_pSourceElement->m_ulMinActiveDur  &&
			    m_pSourceElement->m_ulMinActiveDur > ulDuration))
		    {
			m_pSourceElement->m_ulDuration =
				m_pSourceElement->m_ulAuthoredDur;
			bDoUpdate = TRUE;
		    }
		}
	    }
	    // /If no "dur" or "end" was specified, use the greater of the
	    // media's intrinsic dur and its min without exceeding its max,
	    // if any:
	    else if(((UINT32)-1) == m_pSourceElement->m_ulAuthoredDur)
	    {
		if (m_pSourceElement->m_ulMinActiveDur!=0  &&
			m_pSourceElement->m_ulDuration <
			m_pSourceElement->m_ulMinActiveDur)
		{
		    m_pSourceElement->m_ulDuration =
			    m_pSourceElement->m_ulMinActiveDur;
		    bDoUpdate = TRUE;
		}
		if (((UINT32)-1) != m_pSourceElement->m_ulMaxActiveDur  &&
			m_pSourceElement->m_ulDuration >
			m_pSourceElement->m_ulMaxActiveDur)
		{
		    m_pSourceElement->m_ulDuration =
			    m_pSourceElement->m_ulMaxActiveDur;
		    bDoUpdate = TRUE;
		}
	    }
	    // /If the duration is less than the specified min, use
	    // the min (and we already know that the min < max, so we don't
	    // need to look at the max, if any):
	    else if (m_pSourceElement->m_ulDuration <
			m_pSourceElement->m_ulMinActiveDur)
	    {
		m_pSourceElement->m_ulDuration =
			m_pSourceElement->m_ulMinActiveDur;
		bDoUpdate = TRUE;
	    }
	    // /If the duration authored is greater than the specified max,
	    // use the max (and we already know that the min < max, so we
	    // don't need to look at the min, if any):
	    else if (m_pSourceElement->m_ulDuration >
			m_pSourceElement->m_ulMaxActiveDur)
	    {
		m_pSourceElement->m_ulDuration =
			m_pSourceElement->m_ulMaxActiveDur;
		bDoUpdate = TRUE;
	    }
	    else // /use authored duration:
	    {
		m_pSourceElement->m_ulDuration =
			m_pSourceElement->m_ulAuthoredDur;
		bDoUpdate = TRUE;
	    }

	    if (bDoUpdate)
	    {
		LONG32 lDiff =
			(LONG32)m_pSourceElement->m_ulDuration +
			lBeginOffset;
		m_pSourceElement->m_ulDuration = lDiff>0?
			lDiff : 0;

		m_pParser->resetTimelineElementDuration(m_pID,
			m_pSourceElement->getPureDuration(),
			ulPriorPureDuration);
		// /This keeps track of first-play dur, in case this
		// element restarts during or after playing at least
		// once:
		m_pSourceElement->m_ulOriginalDuration =
			m_pSourceElement->getPureDuration();
		HX_ASSERT(ulDuration == m_pSourceElement->getPureDuration()  ||
			m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
	    }
	}
    }

cleanup:

    if (m_pDependent  &&  ((UINT32)-1 != m_pSourceElement->m_ulDelay))
    {
	HX_ASSERT(WAY_IN_THE_FUTURE >= m_pSourceElement->m_ulDuration +
	        m_pSourceElement->m_ulDelay); // 59584(media version) & 50848 
    }

    if(m_pDependent  &&
	    // /Helps fix PR 66391: If we removed this track because it fell
	    // completely outside its parent's time bounds, then we shouldn't
	    // update our dependent, but rather allow further processing of the
	    // parent seq's setDuration() to remove it's track:
	    !bTrackStartsTooLateSoTrackRemoved  &&
	    // /Helps fix some timing interop cases in the 11.2-11.9 range:
	    ((UINT32)-1 != m_pSourceElement->m_ulDelay)  &&
	    // /Helps fix case where as-yet-unresolved end of seq child should
	    // *not* be used to resolve next sibling's begin: (PR 50848)
	    WAY_IN_THE_FUTURE > m_pSourceElement->m_ulDuration +
	    m_pSourceElement->m_ulDelay) // /+delay for PR 59584-related bug.
    {
	//Removed the addition of m_pSourceElement->m_ulDelay from the
	// source's duration because the source's duration already includes
	// its delay; we don't want to count the delay twice. Fixes PR 13983:
	// /*XXXEH- UNFIXES 13983 by adding back in the ...m_ulDelay addition;
	// the full fix for 13983 requires keeping track of begin=... delay
	// (as opposed to seq-related delay) and then subtracting that begin
	// delay from the m_ulDelay below:
	adjustDependentDuration(m_pDependent);
	// /XXXEH- TODO: figure out if we need to claim this is being set by
	// "parent" (which is really time base) so clip-begin-like action can
	// occur; I don't think so, however:

	// /XXXEH- I think this fixes PR 13983 without breaking other stuff,
	// but need to make sure:
	// /Don't propagate delay of sourceElement (PR 13983) in case its
	// duration already includes its begin offset:
	ULONG32 ulDelayOfSourceElem = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	if (m_pSourceElement->m_bBeginOffsetSet  &&
		m_pSourceElement->m_lBeginOffset > 0)
	{
	    ulDelayOfSourceElem =
		    ((INT32)ulDelayOfSourceElem >
		    m_pSourceElement->m_lBeginOffset ?
		    ulDelayOfSourceElem - m_pSourceElement->m_lBeginOffset :
		    0);

#if defined(XXXEH_DEBUG)
	    HX_ASSERT(!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
		    "ehodge: don't count delay twice!");
#endif
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <=
			m_pSourceElement->m_lBeginOffset); // /PR 6XXXX.
	    }
	}
	// /If this is a repeat element and the first iteration element
	// was clipped due to a negative begin offset, we want to use the
	// full duration for this clip:
	if (m_pDependent->m_pSourceElement->m_pNode->m_repeatTag ==
		RepeatReplica  &&  m_pSourceElement->m_lBeginOffset < 0)
	{
	    ULONG32 ulRepeatIterationFullDur =
		    m_pSourceElement->m_ulOriginalDuration -
		    m_pSourceElement->m_lBeginOffset;
	    if ((UINT32)-1 != m_pSourceElement->m_ulOriginalDuration)
	    {
		m_pDependent->m_pSourceElement->m_ulDuration =
			ulRepeatIterationFullDur;
	    }
	}

	if (WAY_IN_THE_FUTURE < ulDelayOfSourceElem)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulDelayOfSourceElem  &&  "PR 59584");
	    ulDelayOfSourceElem = WAY_IN_THE_FUTURE; // /For PR 59584.
	}

	m_pDependent->setDelay(ulDelayOfSourceElem, FALSE);
    }

    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void
CSmilTimelineElement::setMaxDuration(UINT32 ulMaxDuration)
{
    m_bMaxDurationSet = TRUE;
    m_pSourceElement->m_ulMaxDuration = ulMaxDuration;
}

void 
CSmilTimelineElement::adjustDependentDuration(CSmilTimelineElement* pDependent)
{
    if (m_pParent)
    {
	m_pParent->adjustDependentDuration(m_pDependent);
    }
}

void 
CSmilTimelineElement::resetDelay(UINT32 ulDelay)
{
    INT32   lAdjustedDelay = 0;

    UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
	m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }
    
    if (m_pDependent && m_bDurationSet)
    {
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
        if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(media version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><ref begin="1s" .../><ref begin="1s" .../>...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}
 
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelineElement::resetDelay(%lu):from %lu to %lu;" 
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID, 
	    ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay, 
	    (const char*)m_pDependent->m_pID, ulTotalDelay); 
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif
 
	m_pDependent->resetDelay(ulTotalDelay);
    }
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

    if (m_pSourceElement->m_bRendererInitialized)
    {
	m_pParser->resetTimelineElementDelay(m_pID, m_pSourceElement->m_ulDelay,
		ulPriorDelay);
    }

    // /(Added while fixing PR 59851) Let others know our begin time changed:
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void 
CSmilTimelineElement::resetDuration(UINT32 ulDuration)
{
    INT32 lAdjustedDuration = 0;

    UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();
    
    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	if (!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
		    TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
	}
	lAdjustedDuration = (INT32)ulDuration + m_pSourceElement->m_lBeginOffset;
	m_pSourceElement->m_ulDuration = lAdjustedDuration > 0?lAdjustedDuration:0; 
    }
    else
    {
	m_pSourceElement->m_ulDuration = ulDuration;
    }

    if(m_pParent)
    {
	// /Added surrounding if() to prevent adjusting dur of parent when
	// parent has clearly imposed its dur on *this (helps fix PR 58568)
	if (!m_pSourceElement->m_bCurEndClippedByParent)
	{
	    m_pParent->adjustDuration();
	}
    }

    if(m_pDependent)
    {
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
        if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(media version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><ref begin="1s" .../><ref begin="1s" .../>...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}
 
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelineElement::resetDuration(%lu):from %lu to %lu;"
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulPriorPureDuration, ulDuration, m_pSourceElement->m_ulDuration,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 
 
	// /Helps fix PR 66391; if parent clipped our duration to 0, don't
	// update dependent; that'll be handled in parent seq's setDuration():
	if (0 != ulDuration  &&  !m_pSourceElement->m_bCurEndClippedByParent)
	{
	    m_pDependent->resetDelay(ulTotalDelay);
	}
    }
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void 
CSmilTimelineElement::adjustDuration()
{
    // no-op
    return;
}

HX_RESULT
CSmilTimelineElement::handlePrefetchFinished(UINT32 ulTimeFinished)
{
    HX_RESULT pnr = HXR_FAILED;
    if ((UINT32)-1 != ulTimeFinished)
    {
	if (m_pSourceElement  &&  (UINT32)-1==m_pSourceElement->m_ulDuration)
	{
	    if (m_bDelaySet)
	    {
		if (ulTimeFinished > m_pSourceElement->m_ulDelay)
		{
		    ulTimeFinished -= m_pSourceElement->m_ulDelay;
		}
		else
		{
		    ulTimeFinished = 0;
		}
	    }
	    
	    pnr = HXR_OK;
	    setDuration(ulTimeFinished, FALSE);
	}
    }
    return pnr;
}


void
// /XXXEH- TODO: [20010411] we need to get more information about *what* just
// got resolved so we don't re-resolve the m_pSourceElement on something
// that it already has resolved.  For instance, if the duration of
// pEventElement changed, we only want to resolve or re-resolve
// m_pSourceElement's begin and/or end time that are based on the *end* of
// the event element, and leave be its sync-arcs that are based on the
// *begin* of the event element.
// /XXXEH- TODO: [20010411] Don't set m_bBeginOffsetSet and other vars here;
// wait until the begin|end list is evaluated to get the current
// instance begin|end time (which may not be the sync arc that gets
// resolved herein).  Also, do this for par|seq|excl::elementResolved
CSmilTimelineElement::elementResolved(CSmilTimelineElement* pEventElement)
{
    UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

    BOOL bIsPlayableObjectNotInsertedInTimeline = FALSE;
    if (!pEventElement->m_pSourceElement  ||
	    (pEventElement->m_pSourceElement->m_pNode  &&
	    (m_pParser->isMediaObject(
	    pEventElement->m_pSourceElement->m_pNode)  ||
	    m_pParser->isNonMediaPlayableObject(
	    pEventElement->m_pSourceElement->m_pNode) )  &&
	    !pEventElement->m_pSourceElement->m_bInsertedIntoTimeline) )
    {
	bIsPlayableObjectNotInsertedInTimeline = TRUE;
    }

    // /Fixes SMIL 2.0 Interop Timing #28.2 (which is PR 52571):
    // If eventElement can't begin because it begins and ends before its
    // parent begins, then don't propagate its time to other elements:
    if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
	    pEventElement->m_pSourceElement->m_lBeginOffset < 0)
    {
	if (0 == pEventElement->m_pSourceElement->m_ulDuration)
	{
	    return;
	}
    }

    BOOL bNeedToResolveBeginTimeListVals = FALSE;
    BOOL bNeedToResolveEndTimeListVals = FALSE;
    BOOL bWasInsertedOntoTimeline = FALSE;

    BOOL bIsInExcl = m_pParser->hasAncestor(SMILExcl,
	    m_pSourceElement->m_pNode);
    BOOL bPreviousDelaySetVal = m_bDelaySet;
    BOOL bUseBeginOffsetForPendingBeginList = FALSE;;
    // /If we are in an excl and we are beginning after our excl parent's
    // current child-derived end, then go ahead and insert into the timeline,
    // else see all "We need to go through ..." notes, below.  This fixes
    // Interop Timing cases #9.35 & 9.36 (that broke while fixing 15.13):
    // Note that we don't want to insert ANY element that begins after its
    // parent's immutable end time):
    BOOL bCantExtendParentDuration = FALSE;
    ULONG32 ulParentEnd = (UINT32)-1;
    SMILNode* pSyncBaseNode = m_pParser->getSyncAncestor(
	    m_pSourceElement->m_pNode);
    LONG32 lSourceElementDelayAdjustmentToSyncBaseTime = 0;
    if (pSyncBaseNode  &&  pSyncBaseNode->m_pElement)
    {
	// /XXXEH- TODO: handle case where endsync is SMILEventSourceID and
	// id matches m_pSourceElement->m_pNode->m_id:
	// /XXXEH- TODO: also handle when sync parent has indefinite end|dur:
	if (!pSyncBaseNode->m_pElement->m_bHasExplicitEnd  &&
		!pSyncBaseNode->m_pElement->m_bHasExplicitDur  &&
		(SMILEventSourceFirst !=
		pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag  &&
		SMILEventSourceID !=
		pSyncBaseNode->m_pElement->m_nEndsyncEventSourceTag) )
	{
	    bCantExtendParentDuration = FALSE;
	    if ((UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDuration  &&
		    (UINT32)-1 != pSyncBaseNode->m_pElement->m_ulDelay)
	    {
		ulParentEnd = pSyncBaseNode->m_pElement->m_ulDelay +
			pSyncBaseNode->m_pElement->m_ulDuration;
	    }
	}
	else
	{
	    bCantExtendParentDuration = TRUE;
	    if (bIsPlayableObjectNotInsertedInTimeline)
	    {
		// /Fixes BUG-20010423_nothingShouldPlay_beginBasedOn....smi:
		// If eventElement begins after its parent ends, then don't
		// propagate its time to other elements:
		if ((UINT32)-1 == pEventElement->m_pSourceElement->m_ulDelay  ||
			pEventElement->m_pSourceElement->m_ulDelay >=
			pSyncBaseNode->m_pElement->m_ulDelay +
			pSyncBaseNode->m_pElement->m_ulDuration)
		{
		    return; // /Starts too late.
		}
	    }
	}
    }

    //First, let's see if we have a begin event to resolve:
    // /Combining handling of SMILEventSourceBegin and SMILEventSourceClock
    // fixes SMIL 1.0-syntax PR 112740; the ancient fix for the SMIL2-syntax
    // version is already in the below code; it's about time we combine
    // this code, anyway. (SMILEventSourceClock is only used in SMIL 1.0-
    // syntax syncArcs with clock offsets) :
    if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    // /Be sure not to overflow using ULONGs since
	    // beginEventClockValue might be negative:
	    LONG32 lDelay =
		(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_lBeginEventClockValue;
	    // /Fixes SMIL 2.0 Interop Timing #28.1 and others that have
	    // sync-arc to an element with a negative begin time:
	    if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
		    pEventElement->m_pSourceElement->m_lBeginOffset < 0)
	    {
		lDelay += pEventElement->m_pSourceElement->m_lBeginOffset;
	    }
	    // /Fixes PR 82736 (begin=x.being... case) where sync-arc begin
	    // results in negative offset from parent and we've already
	    // adjusted for that:
	    else if (pSyncBaseNode->m_pElement->m_ulDelay > lDelay  &&
		    // /If already inserted, then adjustForNegativeOffset()
		    // won't re-do any adjustment:
		    m_pSourceElement->m_bInsertedIntoTimeline  &&
		    !m_pSourceElement->m_bIsRestarting)
	    {
		// /Don't go earlier than synbase:
		lDelay = pSyncBaseNode->m_pElement->m_ulDelay;
	    }

	    m_bDelaySet = TRUE;
	    m_pSourceElement->m_ulDelay = lDelay<0? 0: (ULONG32)lDelay;
	    if (lDelay < 0)
	    {
		UINT32 ulDiff = (UINT32)(-lDelay);
		// /If clip-begin is invalid, set it otherwise add to orig:
		m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
		        m_pSourceElement->m_ulAuthoredClipBegin? ulDiff :
			ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
		// /logicChange_test.smi: check if -1 before subtracting delay!:
		if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
		{
		    if (m_pSourceElement->m_ulDuration > ulDiff)
		    {
			m_pSourceElement->m_ulDuration -= ulDiff;
		    }
		    // /else duration is negative; it can't ever play.
		    else
		    {
			m_pSourceElement->m_ulDuration = 0;
		    }
		}
	    }
	    // /Now, if our begin delay (not offset) is based on a syncArc,
	    // we need to adjust our dur by the difference between our delay
	    // and our syncBase element's delay:
	    if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
		    m_pSourceElement->m_bEndOffsetSet  &&
		    WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
	    {
		LONG32 lSum = m_pSourceElement->m_lEndOffset;
		// /We need to remove our delay or it will get counted twice
		lSum -= m_pSourceElement->m_ulDelay;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		m_pSourceElement->m_ulDuration = (UINT32)(lSum<0 ? 0 : lSum);
		// /Fixes PR 80371: If our duration was set before and is now
		// re-resolving, make sure the following flag is reset to false
		// in case it wasn't before, otherwise show/hide code will
		// subtract the delay from a duration that doesn't include the
		// delay:
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = FALSE;
	    }

	    bNeedToResolveBeginTimeListVals = TRUE;
	    if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
	    {
		if (!m_pSourceElement->m_bHasBeenScheduled  ||
			// /Helps fix PR 50588: if restarting, hasBeenSched
			// will still be true, so check if inserted instead:
			(m_pSourceElement->m_bIsRestarting  &&
			!m_pSourceElement->m_bInsertedIntoTimeline) )
		{
		    // /We need to go through the proper channels if we're
		    // in an excl; a priorityClass may prevent us from
		    // starting or may defer our start, so just add us to
		    // the pending begin time list (unless we're extending
		    // the end of our excl parent, as described above):
		    // /First, see if our delay is beyond our parent's end:
		    BOOL bDelayIsBeyondParentEnd = FALSE;
		    if ((UINT32)-1 != ulParentEnd)
		    {
			bDelayIsBeyondParentEnd =
				(m_pSourceElement->m_ulDelay > ulParentEnd);
		    }
		    BOOL bInsertElement = bIsInExcl?
			    (bDelayIsBeyondParentEnd  &&
			    !bCantExtendParentDuration) :
			    ( !(bDelayIsBeyondParentEnd  &&
			    bCantExtendParentDuration) );
		    // /But hold on: if parent's delay isn't yet resolved,
		    // then we can't be inserted until it resolves.  Found
		    // this while fixing long-sync-arc bug PR 64498, par test:
		    // "..._longSyncArcBug-ParWithoutDur...sync.smil":
		    BOOL bParentDelayIsUnresolved = FALSE;
		    if ((UINT32)-1 == pSyncBaseNode->m_pElement->m_ulDelay  ||
			    (pSyncBaseNode->m_pElement->m_pTimelineElement  &&
			    pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelayEvent  &&
			    !pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelaySet ))
		    {
			bInsertElement = FALSE;
			bParentDelayIsUnresolved = TRUE;
		    }

		    if (m_pSourceElement->m_bBeginOffsetSet)
		    {
			// /If it's already been set, then just add this
			// newly-resolved begin time to the pending queue
			// and let it get sorted out there.  This can
			// happen with begin="0s; foo.begin"
			bInsertElement = FALSE;
		    }

		    if (!bInsertElement)
		    {
			// /We need to maintain old "delaySet" value so
			// setDelay() call in eventual call to
			// checkPendingBeginAndEndTimes() can insert this
			// timeline element properly:
			m_bDelaySet = bPreviousDelaySetVal;

			// /Fixes PR 64498: flag the fact that long sync-arc
			// begin is resolving before parent begin is resolved:
			if (bParentDelayIsUnresolved)
			{
			    m_pSourceElement->
				m_bAwaitingSyncAncestorBeginNotification = TRUE;
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    lDelay;
			}
			// /This else-if is the final fix for PR 64499: if
			// sync-base has multiple begin times, then we also
			// need to prepare for that event restarting it even
			// though its first begin is already resolved:
			else if (pSyncBaseNode->m_pElement->m_pBeginTimeList  &&
				pSyncBaseNode->m_pElement->m_pBeginTimeList->
				GetCount() > 1)
			{
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    lDelay;
			}
			else
			{
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    (UINT32)-1;
			}
		    }
		    else
		    {
			bWasInsertedOntoTimeline = TRUE;
			m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    (UINT32)-1;
			m_pParser->insertTimelineElement(m_pID, 
				m_pSourceElement->m_ulDelay);
		    }
		}
	    }
	}
    }
    else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID  &&
	    // /Helps fix SMIL 2.0 Interop Timing #28.9 where end as set by parent
	    // was being used when element's end was actually indefinite (or any
	    // value greater than parent's end); that truncated end time should
	    // not propogate; only the pre-truncated time (if any) should be used:
	    (!pEventElement->m_pSourceElement->m_bCurEndClippedByParent) )
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration )
	{
	    ULONG32 ulPriorDelay = m_pSourceElement->m_ulDelay;
	    m_bDelaySet = TRUE;
	    // /Be sure not to overflow using ULONGs since
	    // beginEventClockValue might be negative:
	    LONG32 lDelay =
		    (LONG32)pEventElement->m_pSourceElement->m_ulDuration +
		    m_pSourceElement->m_lBeginEventClockValue;
	    // /If delay is not set, don't add it!:
	    if(pEventElement->m_bDelaySet)
	    {
		lDelay += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
		// /Fixes case where dur already accounts for begin offset
		// that's already built into the delay (e.g., begin="x.end-5"
		// where x has an explicit begin offset greater than zero):
		// /Helps fix PR 82736 (=x.begin case) by looking at flag and
		// not just blindly assuming beginOffset is included in
		// eventElement's m_ulDuration:
		if (pEventElement->m_pSourceElement->
			m_bDurationIncludesDelayBeyondSyncbase)
		{
		    HX_ASSERT((UINT32)-1 != pEventElement->m_pSourceElement->
			    m_ulBeginOffsetFromSyncBase);
		    if ((UINT32)-1 != pEventElement->m_pSourceElement->
			    m_ulBeginOffsetFromSyncBase)
		    {
			lDelay -= (LONG32)pEventElement->m_pSourceElement->
				m_ulBeginOffsetFromSyncBase;
		    }
		}
		// /Fixes case where third ref has begin="second.end" and
		// second has begin="first.end" where first.end is > 0.
		// In that case, begin offset won't be set but delay WILL
		// alread be part of the duration:
		else if (pEventElement->m_pSourceElement->m_ulDelay >
			pSyncBaseNode->m_pElement->m_ulDelay)
		{
		    ULONG32 ulDelayFromSyncBase =
			    pEventElement->m_pSourceElement->m_ulDelay -
			    pSyncBaseNode->m_pElement->m_ulDelay;
		    HX_ASSERT(lDelay>(LONG32)ulDelayFromSyncBase);
		    if (lDelay < (LONG32)ulDelayFromSyncBase)
		    {
			ulDelayFromSyncBase = lDelay;
		    }
		    lDelay -= (LONG32)ulDelayFromSyncBase;
		}
	    }

	    // /Fixes PR 82736 (begin=x.end... case) where sync-arc begin
	    // results in negative offset from parent and we've already
	    // adjusted for that:
	    if (pSyncBaseNode->m_pElement->m_ulDelay > lDelay  &&
		    // /If already inserted, then adjustForNegativeOffset()
		    // won't re-do any adjustment:
		    m_pSourceElement->m_bInsertedIntoTimeline  &&
		    !m_pSourceElement->m_bIsRestarting)
	    {
		// /Don't go earlier than synbase:
		lDelay = pSyncBaseNode->m_pElement->m_ulDelay;
	    }

	    m_pSourceElement->m_ulDelay = lDelay<0? 0: (ULONG32)lDelay;
	    if (lDelay < 0)
	    {
		UINT32 ulDiff = (UINT32)(-lDelay);
		// /If clip-begin is invalid, set it otherwise add to orig:
		m_pSourceElement->m_ulClipBegin = ((UINT32)-1 ==
		        m_pSourceElement->m_ulAuthoredClipBegin? ulDiff :
			ulDiff+m_pSourceElement->m_ulAuthoredClipBegin);
		if ((UINT32)-1 != m_pSourceElement->m_ulDuration)
		{
		    if (m_pSourceElement->m_ulDuration > ulDiff)
		    {
			m_pSourceElement->m_ulDuration -= ulDiff;
		    }
		    // /else duration is negative; it can't ever play:
		    else
		    {
			m_pSourceElement->m_ulDuration = 0;
#if defined(XXXEH_TESTING)
			HX_ASSERT(m_pSourceElement->m_ulDuration);
#endif
		    }
		}
	    }
	    
	    // /Now, if our begin delay (not offset) is based on a syncArc,
	    // we need to adjust our dur by the difference between our delay
	    // and our syncBase element's delay:
	    if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
		    m_pSourceElement->m_bEndOffsetSet  &&
		    WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
	    {
		LONG32 lSum = m_pSourceElement->m_lEndOffset;
		// /We need to remove our delay or it will get counted twice
		lSum -= m_pSourceElement->m_ulDelay;
		m_pSourceElement->m_ulDuration = (UINT32)(lSum<0 ? 0 : lSum);
	    }

	    bNeedToResolveBeginTimeListVals = TRUE;
	    if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
	    {
		if (!m_pSourceElement->m_bHasBeenScheduled  ||
			// /Fixes PR 50588 (case2): if restarting, hasBeenSched
			// will still be true, so check if inserted instead:
			(m_pSourceElement->m_bIsRestarting  &&
			!m_pSourceElement->m_bInsertedIntoTimeline) )
		{
		    // /See note in code above that handles
		    // m_nBeginEventSourceTag == SMILEventSourceBegin:
		    BOOL bDelayIsBeyondParentEnd = FALSE;
		    if ((UINT32)-1 != ulParentEnd)
		    {
			bDelayIsBeyondParentEnd =
				(m_pSourceElement->m_ulDelay > ulParentEnd);
		    }
		    BOOL bInsertElement = bIsInExcl?
			    (bDelayIsBeyondParentEnd  &&
			    !bCantExtendParentDuration) :
			    ( !(bDelayIsBeyondParentEnd  &&
			    bCantExtendParentDuration) );
		    // /But hold on: if parent's delay isn't yet resolved,
		    // then we can't be inserted until it resolves.  Found
		    // this while fixing long-sync-arc bug PR 64498, par test:
		    // "..._longSyncArcBug-ParWithoutDur...sync.smil":
		    BOOL bParentDelayIsUnresolved = FALSE;
		    if ((UINT32)-1 == pSyncBaseNode->m_pElement->m_ulDelay  ||
			    (pSyncBaseNode->m_pElement->m_pTimelineElement  &&
			    pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelayEvent  &&
			    !pSyncBaseNode->m_pElement->m_pTimelineElement->m_bDelaySet ))
		    {
			bInsertElement = FALSE;
			bParentDelayIsUnresolved = TRUE;
		    }

		    if (m_pSourceElement->m_bBeginOffsetSet)
		    {
			// /If it's already been set, then just add this
			// newly-resolved begin time to the pending queue
			// and let it get sorted out there.  This can
			// happen with begin="0s; foo.begin"
			bInsertElement = FALSE;
		    }

		    if (!bInsertElement)
		    {
			// /See note in code above that handles
			// m_nBeginEventSourceTag == SMILEventSourceBegin:
			m_bDelaySet = bPreviousDelaySetVal;

			// /Fixes "foo.end" version of PR 64498: flag the fact
			// that long sync-arc begin is resolving before parent
			// begin is resolved:
			if (bParentDelayIsUnresolved)
			{
			    m_pSourceElement->
				m_bAwaitingSyncAncestorBeginNotification = TRUE;
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    lDelay;
			}
			// /This else-if is the final fix for foo.end version of
			// PR 64499: if sync-base has multiple begin times, then
			// we also need to prepare for that event restarting it
			// even though its first begin is already resolved:
			else if (pSyncBaseNode->m_pElement->m_pBeginTimeList  &&
				pSyncBaseNode->m_pElement->m_pBeginTimeList->
				GetCount() > 1)
			{
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    lDelay;
			}
			else
			{
			    m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    (UINT32)-1;
			}
		    }
		    else
		    {
			bWasInsertedOntoTimeline = TRUE;
			m_pSourceElement->m_ulLongSyncArcBeginInGroupTime =
				    (UINT32)-1;
			m_pParser->insertTimelineElement(m_pID, 
				m_pSourceElement->m_ulDelay);
		    }
		}
		// /Fixes (part of) SMIL 2.0 Interop Timing #28.9:
		// If already scheduled and possibly even playing, we need to
		// reset the timeline element's delay:
		else if (ulPriorDelay != m_pSourceElement->m_ulDelay)
		{
		    // /Get the matching begin time val, resolve it, and put
		    // it in the pending list:
		    LISTPOSITION lPos = NULL;
		    if (m_pSourceElement->m_pBeginTimeList  &&  NULL !=
			    (lPos = m_pSourceElement->m_pBeginTimeList->
			    GetHeadPosition()) )
		    {
			while (lPos)
			{
			    SmilTimeValue* pTmpVal = (SmilTimeValue*)
				    m_pSourceElement->m_pBeginTimeList->
				    GetNext(lPos);
			    if (pTmpVal)
			    {
				if (SmilTimeSyncBase == pTmpVal->m_type)
				{
				    if (!pTmpVal->isTimeResolved())
				    {
					if (pTmpVal->m_idRef ==
						pEventElement->m_pID)
					{
					    BOOL bATimeWasResolved;
					    m_pSourceElement->resolveSyncArcTimeValues(
						    m_pSourceElement->m_ulDelay +
						    (bUseBeginOffsetForPendingBeginList?
						    m_pSourceElement->m_lBeginOffset:0),
						    (const char*)pEventElement->m_pID,
						    SmilBeginTimeList, bATimeWasResolved,
						    TRUE, m_pParser);
					    bNeedToResolveBeginTimeListVals = FALSE;
					}
				    }
				    else
				    {
					// /else get from pending and change it!
					// See PR 50588 (case 2: begin="x.end")
				    }
				}
			    }
			}
		    }
		}
	    }
	}
    }

    SMILNode* pSyncNode = pSyncBaseNode;
    HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);

    //[SMIL 1.0 compliance] Fixes PR 16629:
    //Next, let's see if we have an end event to resolve:
    // /XXXEH- TODO 20010525: we need to see if there already is an end time
    // that is prior to this new one and is after a begin time; if so, then
    // we want to stick this new one into the pending end time list rather
    // than use it right away:
    // /Combining handling of SMILEventSourceBegin and SMILEventSourceClock
    // fixes SMIL 1.0-syntax version of PR 63622 (part 4) where the fix for
    // part 2 gets resused if we share this code; it's about time we combine
    // this code, anyway:
    if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    m_bDurationSet = TRUE;
	    LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
    		    m_pSourceElement->m_lEndEventClockValue;

	    // /Now, if our begin delay (not offset) is based on a syncArc,
	    // we need to adjust our dur by the difference between our delay
	    // and our syncBase element's delay:
	    if (m_pSourceElement->m_bBeginOffsetSet)
	    {
		if (pSyncNode  &&  pSyncNode->m_pElement)
		{
		    ULONG32 ulSyncBaseDelay =
			    pSyncNode->m_pElement->m_ulDelay;
		    HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
		    if ((UINT32)-1 != ulSyncBaseDelay)
		    {
			HX_ASSERT(m_pSourceElement->m_ulDelay >=
				ulSyncBaseDelay);
			if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay)
			{
			    lSum -= (LONG32)ulSyncBaseDelay;
			}
				
		    }
		}
	    }
	    // /Checking these two conditionals helps fix PR 63622 (part 2):
	    else if (m_bDelaySet  &&  m_pSourceElement->m_ulDelay!=(UINT32)-1)
	    {
		// /We need to remove our delay or it will get counted twice:
		lSum -= m_pSourceElement->m_ulDelay;
	    }

	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.

	    m_pSourceElement->m_ulDuration = (UINT32)lSum;
	    // /Fixes case where parent dur was overriding this new
	    // m_ulDuration, above, in this's subsequent setDuration(d,TRUE)
	    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulAuthoredDur)
	    {
		// /Change "core-tricking" value back to unset:
		m_pSourceElement->m_ulAuthoredDur = (UINT32)-1;
	    }
	    // /Fixes case where both dur=d & end=x.begin were specified;
	    // use the lesser of the two (part 4 of PR 71386):
	    else if (m_pSourceElement->m_bHasExplicitDur  &&
		    (UINT32)-1 != m_pSourceElement->m_ulAuthoredDur  &&
		    m_pSourceElement->m_ulAuthoredDur < (UINT32)lSum)
	    {
		m_pSourceElement->m_ulDuration =
			m_pSourceElement->m_ulAuthoredDur;
	    }

	    bNeedToResolveEndTimeListVals = TRUE;

	    // /More of fix for PR 63622 (part 2): if our delay isn't set, then
	    // when it does resolve, treat it as an end, not a relative dur:
	    if (!m_bDelaySet  ||  m_pSourceElement->m_ulDelay==(UINT32)-1)
	    {
		/* Removing this doesn't (now) affect PR 63622 part 2, which
		 * still plays fine, while removing it *does* fix PR 81256
		 * where an element wasn't restarting because its end time
		 * (in its list) wasn't considered resolved on the next play:
		// /For PR 63622 (part 2): don't resolve end time(s) since
		// begin delay isn't resolved yet:
		bNeedToResolveEndTimeListVals = FALSE;
		 */
		if (!m_pSourceElement->m_bEndOffsetSet)
		{
		    m_pSourceElement->m_bEndOffsetSet = TRUE;
		    m_pSourceElement->m_lEndOffset = (UINT32)lSum;
		}
	    }
	    // /Helps fix PR 63622 (part 2): changed this to "*else* if" since
	    //  we don't want to do anything until our begin delay is set:
	    else if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID))
	    {
		if (!m_pSourceElement->m_bHasBeenScheduled  ||
			// /Fixes PR 50588 (case4): if restarting, hasBeenSched
			// will still be true, so check if inserted instead:
			(m_pSourceElement->m_bIsRestarting  &&
			!m_pSourceElement->m_bInsertedIntoTimeline) )
		{
		    bWasInsertedOntoTimeline = TRUE;
		    m_pParser->insertTimelineElement(m_pID, 
			m_pSourceElement->m_ulDelay);
		}
		// /Be sure to update the timeline; fixes variant of PR 59801
		// when end="x.begin" instead of end="x.end":
		else
		{
		    m_pParser->resetTimelineElementDuration(
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->getPureDuration(),
			    ulPriorPureDuration);
		    m_pParser->m_pTimelineElementManager->notify(
			    (const char*)m_pSourceElement->m_pNode->m_id);
		}
	    }
	}
    }
    else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration)
	{
	    m_bDurationSet = TRUE;

	    LONG32 lSum =(LONG32)pEventElement->getDuration() +
		    m_pSourceElement->m_lEndEventClockValue;
	    // /If the event element has a delay, we need to add that
	    // minus any beginOffset (if it's set); subtracting the begin
	    // offset fixes "BUG-20000921_beginSyncArcOffBy5secInBlue.smi":
	    if(pEventElement->m_bDelaySet)
	    {
		lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
		if (pEventElement->m_pSourceElement->m_bBeginOffsetSet  &&
			pEventElement->m_pSourceElement->m_lBeginOffset > 0)
		{
		    lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
		    // /20020630- Find content that may be broken if this
		    // asserts.  If such a thing exists, change above call to
		    // "...->getDuration()" to "...->getPureDuration()" and
		    // then total delay:
		    HX_ASSERT(pEventElement->m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase);
		}
		// /Final nail in PR 77406's coffin: if begin of event element
		// was event based and thus there's no m_bBeginOffsetSet but
		// there *is* a m_ulBeginOffsetFromSyncBase>0, then we need to
		// subtract that if it's included in the duration:
		else if (pEventElement->m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
			pEventElement->m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
			pEventElement->m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
		{
		    lSum -= pEventElement->m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	    else
	    {
		HX_ASSERT(pEventElement->m_bDelaySet);
	    }
	    // /lSum is now in global (group) time space.  We need to convert
	    // it into this's local time space:

	    // /Now, if our begin delay (not offset) is based on a syncArc,
	    // we need to adjust our dur by the difference between our delay
	    // and our syncBase element's delay:
	    if (m_pSourceElement->m_bBeginOffsetSet)
	    {
		if (pSyncNode  &&  pSyncNode->m_pElement)
		{
		    ULONG32 ulSyncBaseDelay =
			    pSyncNode->m_pElement->m_ulDelay;
		    HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
		    if ((UINT32)-1 != ulSyncBaseDelay)
		    {
			HX_ASSERT(m_pSourceElement->m_ulDelay >=
				ulSyncBaseDelay);
			if (m_pSourceElement->m_ulDelay > ulSyncBaseDelay)
			{
			    lSum -= (LONG32)ulSyncBaseDelay;
			}
				
		    }
		}

		// /This fixes PR 8XXXZ (PR 63622 revisited): if begin is set and duration includes
		// that begin delay, subtract it from the sum & reset the flag:
		if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
		{
		    lSum -= m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0?
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase : 0;
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
			    FALSE;
		}
	    }
	    // /Checking these two conditionals helps fix PR 63622 (part 3):
	    else if (m_bDelaySet  &&  m_pSourceElement->m_ulDelay!=(UINT32)-1)
	    {
		// /We need to remove our delay or it will get counted twice:
// /XXXEH- 20020625: maybe subtract curBeginOffsetFromSyncBase (as 10 lines above) instead?:
		lSum -= m_pSourceElement->m_ulDelay;
	    }

	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.

	    m_pSourceElement->m_ulDuration = (UINT32)lSum;
            BOOL bDurationWasPreviouslyUnresolvedIndefinite = FALSE;
	    // /Fixes case where parent dur was overriding this new
	    // m_ulDuration, above, in this's subsequent setDuration(d,TRUE)
	    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulAuthoredDur)
	    {
                bDurationWasPreviouslyUnresolvedIndefinite = TRUE;
		// /Change "core-tricking" value back to unset:
		m_pSourceElement->m_ulAuthoredDur = (UINT32)-1;
	    }
	    // /Fixes case where both dur=d & end=x.end were specified;
	    // use the lesser of the two (part 2 of PR 71386):
	    else if (m_pSourceElement->m_bHasExplicitDur  &&
		    (UINT32)-1 != m_pSourceElement->m_ulAuthoredDur  &&
		    m_pSourceElement->m_ulAuthoredDur < (UINT32)lSum)
	    {
		m_pSourceElement->m_ulDuration =
			m_pSourceElement->m_ulAuthoredDur;
	    }

	    bNeedToResolveEndTimeListVals = TRUE; 
  
	    // /More of fix for PR 63622 (part 3): if our delay isn't set, then 
	    // when it does resolve, treat it as an end, not a relative dur: 
	    if (!m_bDelaySet  ||  m_pSourceElement->m_ulDelay==(UINT32)-1) 
	    { 
		/* Removing this doesn't (now) affect PR 63622 part 3, which
		 * still plays fine, while removing it *does* fix PR 81256
		 * where an element wasn't restarting because its end time
		 * (in its list) wasn't considered resolved on the next play:
		// /For PR 63622 (part 3): don't resolve end time(s) since 
		// begin delay isn't resolved yet: 
		bNeedToResolveEndTimeListVals = FALSE;
		 */
		if (!m_pSourceElement->m_bEndOffsetSet) 
		{ 
		    m_pSourceElement->m_bEndOffsetSet = TRUE; 
		    m_pSourceElement->m_lEndOffset = (UINT32)lSum; 
		} 
	    } 
	    // /Helps fix PR 63622 (part 3): changed this to "*else* if" since 
	    //  we don't want to do anything until our begin delay is set: 
	    else if (HXR_OK == m_pParser->adjustForNegativeOffset(m_pID)) 
	    {
		if (!m_pSourceElement->m_bHasBeenScheduled  ||
			// /Fixes PR 50588 (case5): if restarting, hasBeenSched
			// will still be true, so check if inserted instead:
			(m_pSourceElement->m_bIsRestarting  &&
			!m_pSourceElement->m_bInsertedIntoTimeline) )
		{
		    bWasInsertedOntoTimeline = TRUE;
		    m_pParser->insertTimelineElement(m_pID, 
			m_pSourceElement->m_ulDelay);
		}
		// /Fixes PR 59801: the fix for PR 50535, which enabled
		// inserting of an element into the timeline before its end
		// event is resolved (as is needed when end="foo.end" and foo
		// has an event-based end) caused parent to extend to that
		// WAY_IN_THE_FUTURE dur and never brought it back in when
		// the end time resolved, so here goes:
                // /Adding the if() part to the else helps fix PR 107724: don't
                // go through all this code if this element has not had its
                // duration altered by the code, above:
                else if (m_pSourceElement->getPureDuration() !=
                        ulPriorPureDuration)
		{
		    // /This fixes PR 70437 where temporary, indefinite
		    // duration had been added to parent, earlier, while
		    // waiting for when (or if) sync-arc'd element's end
		    // ever resolves.  Then, when it resolved, parent wasn't
		    // being notified of this new duration, thus the temporary
		    // indef duration remained as the presentation duration:
		    m_bDurationSet=FALSE; // /Force override to new value.
		    HX_ASSERT(m_pSourceElement->m_ulDuration ==
			    m_pSourceElement->getPureDuration());
		    m_pParser->durationResolved(
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->m_ulDuration, FALSE);

		    m_pParser->resetTimelineElementDuration(
			    (const char*)m_pSourceElement->m_pNode->m_id,
			    m_pSourceElement->getPureDuration(),
			    ulPriorPureDuration);

                    // /Helps fix PR 107724: add duration to parent if
                    // it was added before as unresolved indefinite:
                    if (m_pSourceElement->m_bAddDurationAlreadyDone  &&
                            bDurationWasPreviouslyUnresolvedIndefinite)
                    {
                        m_pParent->addDuration( 
                                m_pSourceElement->m_ulDuration, 
                                m_pSourceElement->m_ulDelay,
                                m_pSourceElement->m_ulBeginOffsetFromSyncBase,
                                m_pID);
                    }

		    m_pParser->m_pTimelineElementManager->notify(
			    (const char*)m_pSourceElement->m_pNode->m_id);
		}
	    }
	}
    }

    BOOL bMoveNewlyResolvedsToPendingTimeList =
	    !bWasInsertedOntoTimeline;
    if (bNeedToResolveBeginTimeListVals)
    {
	BOOL bATimeWasResolved;
	m_pSourceElement->resolveSyncArcTimeValues(
		m_pSourceElement->m_ulDelay +
		(bUseBeginOffsetForPendingBeginList?
		m_pSourceElement->m_lBeginOffset:0),
		(const char*)pEventElement->m_pID,
		SmilBeginTimeList, bATimeWasResolved,
		bMoveNewlyResolvedsToPendingTimeList,
		m_pParser);
    }
    if (bNeedToResolveEndTimeListVals)
    {
	// /Fixes PR 81828: if delay is unresolved but end time was just
	// resolved, above, then use end not the invalid sum of dur+delay:
	ULONG32 ulEndTime = m_pSourceElement->m_ulDuration +
		m_pSourceElement->m_ulDelay;
	if ((UINT32)-1 == m_pSourceElement->m_ulDelay  ||
		(UINT32)-1 == m_pSourceElement->m_ulDuration)
	{
	    ulEndTime = m_pSourceElement->m_lEndOffset;
	}
	// /Helps fix PR 79699 (case where trackDurationResolved call order
	// is: flash, msd, vid):
	else if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase  &&
		m_pSourceElement->m_ulBeginOffsetFromSyncBase > 0)
	{
	    ulEndTime -= m_pSourceElement->m_ulBeginOffsetFromSyncBase;
	}

	BOOL bATimeWasResolved;
	m_pSourceElement->resolveSyncArcTimeValues(
		// /Use dur+delay, not just delay here (as can be proven when
		// doing the following: begin="foo.end" end="foo.end+5s"
		// where foo.begin > 0:
		ulEndTime,
		(const char*)pEventElement->m_pID,
		SmilEndTimeList, bATimeWasResolved,
		bMoveNewlyResolvedsToPendingTimeList,
		m_pParser);
    }

    // XXXMEH - we need to check here if we should
    // update the remove time
    checkElementFillBehavior();
}

#if 0
void
CSmilTimelineElement::setEvent(SMILEventSourceTag eTag,
				SMILSyncAttributeTag aTag,
				const char* pEventSourceID,
				UINT32 ulEventClockValue)
{
    m_eEventSourceTag = eTag;
    m_eSyncAttributeTag = aTag;
    if(pEventSourceID)
    {
	m_pEventSourceID = new char[strlen(pEventSourceID)+1];
	strcpy(m_pEventSourceID, pEventSourceID); /* Flawfinder: ignore */
	m_pParser->m_pTimelineElementManager->addNotification(pEventSourceID, this);
    }
    m_ulEventClockValue = ulEventClockValue;
}
#endif


void 
CSmilTimelineElement::addChild(CSmilTimelineElement* pChild)
{
    if(!m_pChildren)
    {
	m_pChildren = new CHXSimpleList;
    }
    m_pChildren->AddTail(pChild);
    pChild->setParent(this);
}

UINT32
CSmilTimelineElement::getDuration()
{
    return m_pSourceElement->m_ulDuration;
}

UINT32
CSmilTimelineElement::getDelay()
{
    return m_pSourceElement->m_ulDelay;
}

void 
CSmilTimelineElement::dump()
{
}

void CSmilTimelineElement::checkChildrenFillBehavior()
{
    if (m_pChildren && m_pParser)
    {
        LISTPOSITION pos = m_pChildren->GetHeadPosition();
        while (pos)
        {
            CSmilTimelineElement* pTime =
                (CSmilTimelineElement*) m_pChildren->GetNext(pos);
            if (pTime &&
                pTime->m_pSourceElement &&
                pTime->m_pSourceElement->m_pNode)
            {
                const char* pszID          = (const char*) pTime->m_pSourceElement->m_pNode->m_id;
                UINT32      ulComputedTime = 0;
                HX_RESULT   retVal         = m_pParser->computeRemoveTime(pszID, ulComputedTime);
                if (SUCCEEDED(retVal))
                {
// /#define XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT
#if defined(_DEBUG)  &&  defined(XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT)
{
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", "a+");
    ::fprintf(f1, "checkChildrenFillBehavior() of %s, computed time=%lu, m_ulRemoveTime=%lu, m_ulDelay=%lu, m_ulDuration=%lu\n",
	pszID, ulComputedTime, pTime->m_pSourceElement->m_ulRemoveTime, pTime->m_pSourceElement->m_ulDelay, pTime->m_pSourceElement->m_ulDuration);
    ::fclose(f1);
}
#endif
                    // We've successfully computed the remove time - does
                    // this remove time match when we have the hide event scheduled?
                    if (ulComputedTime != pTime->m_pSourceElement->m_ulRemoveTime)
                    {
#if defined(_DEBUG)  &&  defined(XXXEHODGE_DEBUG_REMOVE_TIME_OF_VISUAL_ELEMENT)
{
    FILE* f1 = ::fopen("c:\\smil2excl.txt", "a+");
    ::fprintf(f1, "\tcheckChildrenFillBehavior() called [%s]->updateRemoveTime(%lu   <--(%lu) ), m_ulDelay=%lu, m_ulDuration=%lu\n",
	pszID, ulComputedTime, pTime->m_pSourceElement->m_ulRemoveTime, pTime->m_pSourceElement->m_ulDelay, pTime->m_pSourceElement->m_ulDuration);
    ::fclose(f1);
}
#endif
                        // We need to update the hide event
                        pTime->m_pSourceElement->updateRemoveTime(ulComputedTime);
                    }
                    // If this child has a fill="freeze" or a fill="hold",
                    // then we need to check this child's children
                    if (pTime->m_pSourceElement->m_eActualFill == FillFreeze ||
                        pTime->m_pSourceElement->m_eActualFill == FillHold)
                    {
                        pTime->checkChildrenFillBehavior();
                    }
                }
            }
        }
    }
}

void CSmilTimelineElement::checkElementFillBehavior()
{
    if (m_pSourceElement &&
        m_pSourceElement->m_pNode)
    {
        const char* pszID          = (const char*) m_pSourceElement->m_pNode->m_id;
        UINT32      ulComputedTime = 0;
        HX_RESULT   retVal         = m_pParser->computeRemoveTime(pszID, ulComputedTime);
        if (SUCCEEDED(retVal))
        {
            // We've successfully computed the remove time - does
            // this remove time match when we have the hide event scheduled?
            if (ulComputedTime != m_pSourceElement->m_ulRemoveTime)
            {
//                char szDbgStr[128];
//                DEBUGPRINTF(szDbgStr, "Updating id=%s remove time from %lu to %lu\n",
//                            pszID, m_pSourceElement->m_ulRemoveTime, ulComputedTime);
                // We need to update the hide event
                m_pSourceElement->updateRemoveTime(ulComputedTime);
            }
        }
    }
}

void CSmilTimelineElement::setParExclDuration(UINT32 ulDuration, BOOL bSetFromParent)
{
    m_pSourceElement->m_ulDuration = ulDuration;
    // /Don't go past end of parent; fixes PR65741-related event-begun par
    if (m_pSourceElement->m_ulDuration > m_pSourceElement->m_ulMaxDuration)
    {
	m_pSourceElement->m_ulDuration = m_pSourceElement->m_ulMaxDuration;
    }
    m_bDurationSet = TRUE;
    if(m_pChildren  &&
	    // /If not set from parent, make sure we've completely resolved
	    // our duration before forcing it on the kids (broken by fix for
	    // PR 61174(version1).  Fixes PR 56686 version 7:
	    (bSetFromParent  ||  m_pSourceElement->m_bAddDurationAlreadyDone
	    // /Explicit end or dur, so OK to possibly clip children; helps
	    // reduce cases where PR 65676 occurs by setting max durs on kids:
	    ||  m_pSourceElement->m_bHasExplicitEnd
	    ||  m_pSourceElement->m_bHasExplicitDur))
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
	    pElement->setDuration(m_pSourceElement->m_ulDuration, TRUE);
        }
    }

    //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void CSmilTimelineElement::setParExclMaxDuration(UINT32 ulMaxDuration)
{
    HX_ASSERT(m_pChildren);
    m_bMaxDurationSet = TRUE;
    m_pSourceElement->m_ulMaxDuration = ulMaxDuration;

    if (m_pChildren  &&  m_bDelaySet)
    {
	HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);

	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
	    pElement->setMaxDuration(ulMaxDuration);
	}
    }
}

void CSmilTimelineElement::parExclElementResolved(CSmilTimelineElement* pEventElement)
{
    // /Fixes PR 56233 (par version): if this par is resolving an end time
    // based on another element's timing and that other element is a
    // descendant of this par, then we'll get in an infinite loop when this
    // par clips its child's end, causing the child to update its end, causing
    // this par to get another elementResolved, ad infinitum.  Now, we lock
    // elementResolved() on this element by setting its m_bInElementResolved
    // flag and resetting it only when this method has completed:
    if (m_bInElementResolved)
    {
	goto cleanup;
    }
    m_bInElementResolved = TRUE;

    //First, let's see if we have a begin event to resolve:
    // /Combine handling of SMILEventSourceBegin and SMILEventSourceClock;
    // the latter is only used in SMIL 1.0-syntax syncArcs with clock offsets:
    if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    // /Note: no longer subtracting pEventElement->m_pSourceElement->
	    // m_ulBeginOffsetFromSyncBase from the sum in the following
	    // if/else fixes PR 66352 while allowing PR 14420 (SMIL2-excl
	    // version) to still work

	    //[SMIL 1.0 Compliance] Helps fix 14420:
	    if (m_bNonEventDelaySet)
	    {
		//Add non-event delay to syncArc element delay + clock offset:
		//Do the following in case sum is negative; if so, we
		// want to use zero.
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
	    }
	    else
	    {
		//Just set delay to syncArc element delay + clock offset:
		//Do the following in case sum is negative; if so, we
		// want to use zero.
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = (ULONG32)lSum;
		m_ulNonEventDelay = 0;
	    }
	    m_bNonEventDelaySet = m_bDelaySet = TRUE;
	    if(m_pChildren)
	    {
		CHXSimpleList::Iterator i = m_pChildren->Begin();
		for(; i != m_pChildren->End(); ++i)
		{
		    CSmilTimelineElement* pElement =
			    (CSmilTimelineElement*)(*i);
		    pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		}
	    }
	}
    }
    else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration)
	{
	    //[SMIL 1.0 Compliance] Helps fix 14420:
	    if (m_bNonEventDelaySet)
	    {
		//Add non-event delay to syncArc element end + clock offset:
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDuration +
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
	    }
	    else
	    {
		//Just set delay to syncArc element end + clock offset:
		//Do the following in case sum is negative; if so, we
		// want to use zero.
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDuration +
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = (ULONG32)lSum;
		m_ulNonEventDelay = 0;
	    }
	    m_bNonEventDelaySet = m_bDelaySet = TRUE;
	    if(m_pChildren)
	    {
		CHXSimpleList::Iterator i = m_pChildren->Begin();
		for(; i != m_pChildren->End(); ++i)
		{
		    CSmilTimelineElement* pElement =
			    (CSmilTimelineElement*)(*i);
		    pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		}
	    }
	}
    }

    
    // /Combine handling of SMILEventSourceBegin and SMILEventSourceClock;
    // the latter is only used in SMIL 1.0-syntax syncArcs with clock offsets:
    if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
    		    m_pSourceElement->m_lEndEventClockValue;
	    if (m_bDelaySet)
	    {
		// /Fixes bug where the following had a dur that didn't
		// account for its offset:
		// <par begin="3s" end="foo.begin+5s" />
		lSum -= m_pSourceElement->m_ulDelay;
	    }
	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
	    // /Fixes PR 43068:
	    m_bDurationSet = FALSE; // /We want to force override to lSum.
	    parExclDurationResolved((ULONG32)lSum, TRUE);
	}
    }
    else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration)
	{
	    LONG32 lSum =(LONG32)pEventElement->getDuration() +
		    m_pSourceElement->m_lEndEventClockValue;
	    // /If the event element has a delay, we need to add that
	    // minus any beginOffset (if it's set):
	    if(pEventElement->m_bDelaySet)
	    {
		lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
		if (pEventElement->m_pSourceElement->m_bBeginOffsetSet)
		{
		    HX_ASSERT(0  &&  "ehodge: does this code work?!");
		    lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
		}
	    }
	    if (m_bDelaySet)
	    {
		// /Fixes bug where the following had a dur that didn't
		// account for its offset:
		// <par begin="3s" end="foo.end+5s" />
		lSum -= m_pSourceElement->m_ulDelay;
	    }
	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
	    // /Fixes PR 43068:
	    m_bDurationSet = FALSE; // /We want to force override to lSum.
	    parExclDurationResolved((ULONG32)lSum, TRUE);
	}
    }

    m_bInElementResolved = FALSE;

cleanup:
    return;
}

void CSmilTimelineElement::parExclDurationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineElement{%s}::parExclDurationResolved(dur=%lu, bUpdateChildren=%d, "
		"m_bDurationSet=%sE (cur m_ulDuration=%lu) m_bAddDurationAlreadyDone=%d\n",
		(const char*)m_pID, ulDuration, bUpdateChildren, m_bDurationSet?"TRU":"FALS",
		m_pSourceElement->m_ulDuration, m_pSourceElement->m_bAddDurationAlreadyDone);
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    if(!m_bDurationSet  ||
	    // /Final fix for PR 52110: we need to make sure parent and
	    // dependent, if any, get told of our duration even if our
	    // duration has already been set, which can happen if we have
	    // an explicit end or dur.  We should go ahead and add ourself to
	    // the parent if we haven't already done so:
	    !m_pSourceElement->m_bAddDurationAlreadyDone)
    {
	// /(Note: if endsync="first" causes re-resolving of duration, then
	// it's perfectly valid for bUpdateChildren to be TRUE here.)

	m_bDurationSet = TRUE;
	m_pSourceElement->m_ulDuration = ulDuration;
	if(m_pParent)
	{
	    ULONG32 ulDelayFromSyncBaseBegin = 0;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
	    {
		ulDelayFromSyncBaseBegin =
			m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		if (ulDelayFromSyncBaseBegin > 0  &&
			!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
		{
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
			    TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
		    m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
		}
	    }
	    m_pParent->addDuration(m_pSourceElement->m_ulDuration,
		    m_pSourceElement->m_ulDelay,
		    ulDelayFromSyncBaseBegin, m_pID);
	    m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
	}
	if(m_pDependent)
	{
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	    ULONG32 ulTotalDelay = 0;
	    if (HXR_OK !=
		    m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	    {
		goto doneSettingDependent;
	    }
#else
	    ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		    m_pSourceElement->m_ulDuration;
	    // /Helps fix PR 6XXXX(par version): if delay is already packed
	    // into the duration, then don't count it twice (as can happen in
	    // <seq><par begin="1s">...</par><par begin="1s" ...):
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
		{
		    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay);
		    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay)
		    {
			ulTotalDelay -=
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		    }
		}
	    }
#endif

	    if (WAY_IN_THE_FUTURE < ulTotalDelay)
	    {
		ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584 (par2).
	    }
	    // /helps fix PR 62688 (case2) where outer seq has media after
	    // par w/endsync="all": don't adjustDep.Dur. if delay is indef.:
	    if ((m_pDependent->getDelay() != (UINT32)-1  &&
		    m_pDependent->getDelay() >= WAY_IN_THE_FUTURE)  ||
		    // /Helps fix PR 59584 (parFollowsPar version): also don't
		    // adjustDep.Dur. if we're about to set the delay to indef
		    (m_pDependent->getDelay() == (UINT32)-1  &&
		    WAY_IN_THE_FUTURE == ulTotalDelay) )
	    {
   		HX_ASSERT(ulTotalDelay==WAY_IN_THE_FUTURE  &&  "send content to ehodge");
	    }
	    else
	    {
		adjustDependentDuration(m_pDependent);
	    }

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
{
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE :
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
    ::fprintf(f1, "\n\t%s:CSmilTimelineElement::parExclDurationResolved();\tsetting dependent (%s)'s delay to %lu\n",
	    (const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1);
    bFirstTimeAddDurDebugout = FALSE;
}
#endif
	    // /XXXEH- TODO: figure out if we need to claim this is being set
	    // by "parent" (which is really time base) so clip-begin-like
	    // action can occur; I don't think so, however:
	    m_pDependent->setDelay(ulTotalDelay, FALSE);	    
	}
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

	if(bUpdateChildren)
	{
	    UINT32 ulNumChildrenDursSet = 0;
	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    for(; i != m_pChildren->End(); ++i)
	    {
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
		// /If child has no resolved, scheduled begin time yet, then
		// for crying out loud don't set its duration yet.  This is
		// needed in the case where *this has endsync="all":
		if (SMILEventSourceAll !=
			m_pSourceElement->m_nEndsyncEventSourceTag  ||
			pElement->m_pSourceElement->m_bInsertedIntoTimeline)
		{
		    ulNumChildrenDursSet++;
		    // /Don't set the child's duration unless the new duration
		    // is less than the child's existing duration; the SMIL
		    // spec says that a parent element can not extend the
		    // duration of a child; fixes PR 50572:
		    if (pElement->m_pSourceElement  &&  ( (UINT32)-1 ==
			    pElement->m_pSourceElement->m_ulDuration  ||
			    pElement->m_pSourceElement->m_ulDuration >
			    m_pSourceElement->m_ulDuration) )
		    {
    			pElement->setDuration(m_pSourceElement->m_ulDuration,
				TRUE);
		    }
		}
	    }
	}
    }
    // Check our children's fill behavior
    checkChildrenFillBehavior();
    //[SMIL 1.0 Compliance] Helps fix PR 14420 and 23025:
    // if a source has event-based timing based on this seq's
    // begin time (delay) then we need to notify that source
    // that we've resolved this value:
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

/***************************************************************************/

/*
 * CSmilTimelinePar methods
 */

CSmilTimelinePar::CSmilTimelinePar(CSmilElement* pSourceElement,
				   CSmilParser* pParser):
    CSmilTimelineElement(pSourceElement, pParser),
    m_nDurationAdded(0),
    m_ulFirstDuration(0),
    m_bFirstDurationHasBeenSet(FALSE),
    m_ulLastDuration(0)
{
}

CSmilTimelinePar::~CSmilTimelinePar()
{
}

void 
CSmilTimelinePar::setDelay(UINT32 ulDelay,
	   // /NOTE: we ignore this in time containers that aren't media:
	   BOOL bSetByParent)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelinePar{%s}::setDelay(delay=%lu, "
		"bSetByParent=%sE) m_bDelaySet=%sE, beginOffset=%lu\n",
		(const char*)m_pID, ulDelay,
		bSetByParent?"TRU":"FALS",
		m_bDelaySet?"TRU":"FALS", m_pSourceElement->m_lBeginOffset);
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	m_pSourceElement->m_ulDelay = (
		((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
		(UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }
    if (!m_bDelayEvent) //[SMIL 1.0 compliance] helps fix PR 14420.
    {
	m_bDelaySet = TRUE;
	ULONG32 ulNumChildrenWithNonEventBasedBegins = 0;
	if(m_pChildren)
	{
	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    for(; i != m_pChildren->End(); ++i)
	    {
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
		pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		if (pElement->m_pSourceElement  &&  pElement->m_pSourceElement->
			m_bHasAtLeastOneNonEventBasedBegin)
		{
		    ulNumChildrenWithNonEventBasedBegins++;
		}
	    }
	}
	// /Fixes PR 24046 (SMIL 2+ par version): if there are no children,
	// then the par's duration is zero, so set it to 0:
	if ((!m_pChildren  &&  m_pSourceElement->m_ulDuration == (UINT32)-1)  ||
		0 == ulNumChildrenWithNonEventBasedBegins)
	{
	    // /Checking 1st for explicit end or dur re-fixes PR 57150(par)
	    // which was broken by fix for PR 24046 (note: PR 57150 has dur=x
	    // *and* endsync="all" which is a strange thing to author):
	    if (!m_pSourceElement->m_bHasExplicitDur  &&
		    !m_pSourceElement->m_bHasExplicitEnd)
	    {
		m_pSourceElement->m_ulDuration = 0;
	    }
	    // /Helps fix PR 62688(par version): if all children are
	    // event-begun and there is at least one child, and endsycn="all",
	    // then we have an indefinite duration until all child ends resolve:
	    if (m_pChildren  &&  SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag  &&
		    // /Ignore endsync if it has explicit end or dur:
		    !m_pSourceElement->m_bHasExplicitDur  &&
		    !m_pSourceElement->m_bHasExplicitEnd)
	    {
		m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
	    }
	}

	if (m_pSourceElement->m_ulDuration != (UINT32)-1)
	{
	    setDuration(m_pSourceElement->m_ulDuration);
#if 0 //20011024-0
	    // /Fixes PR 61174(version1) and par version of PR 56686
	    // (version1): we know our duration already, so let's declare it
	    // resolved so we get added to our parent (in case none of our
	    // children have scheduled begin times in which case our
	    // ::addDuration() would not get called up front and the overall
	    // presentation would not include our duration at first):
	    if (m_pSourceElement->m_bHasExplicitDur  ||
		    m_pSourceElement->m_bHasExplicitEnd  ||
		    // /For PR 62688(par version) and other endsync="all" bugs:
		    SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		// /Be sure not to override a shorter duration that may have
		// been imposed on us by our parent:
		if (!m_bDurationSet  ||
			!m_pSourceElement->m_bAddDurationAlreadyDone)
		{
		    HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
		    durationResolved(m_pSourceElement->m_ulDuration, FALSE);
		}
		HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
	    }
#else /* At least fix it for endsync="all":*/
	    // /Fixes PR 61174(version1) and par version of PR 56686
	    // (version1): we know our duration already, so let's declare it
	    // resolved so we get added to our parent (in case none of our
	    // children have scheduled begin times in which case our
	    // ::addDuration() would not get called up front and the overall
	    // presentation would not include our duration at first):
	    if ((!m_pSourceElement->m_bHasExplicitDur  &&
		    !m_pSourceElement->m_bHasExplicitEnd)  &&
		    // /For PR 62688(par version) and other endsync="all" bugs:
		    SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		// /Be sure not to override a shorter duration that may have
		// been imposed on us by our parent:
		if (!m_bDurationSet  ||
			!m_pSourceElement->m_bAddDurationAlreadyDone)
		{
		    HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
		    HX_ASSERT(m_pSourceElement->m_ulDuration ==
			    m_pSourceElement->getPureDuration());
		    durationResolved(m_pSourceElement->m_ulDuration, FALSE);
		}
		HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
	    }
#endif
	}
    }
    else //[SMIL 1.0 compliance] for PR 14420:
	// let's not claim that the delay is set when we still
	// are awaiting a delay (begin) event; we *do* need to
	// add the delay of this to the event's begin offset.
	// This is done by setting the new "m_bNonEventDelaySet"
	// variable to TRUE and leaving m_bDelaySet to FALSE
	// until the ElementResolved() call sets it to true:
    {
	//Parent calls setDelay before we get to ElementResolved,
	// thus m_bDelaySet should never be TRUE if we have a
	// delay event:
	HX_ASSERT(!m_bDelaySet);
	m_bNonEventDelaySet = TRUE; //ElementResolved will look at this.
	m_ulNonEventDelay = ulDelay;
    }
    
    if(m_pDependent  &&  m_bDurationSet)
    {
	adjustDependentDuration(m_pDependent);

#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(par version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><par begin="1s">...</par><par begin="1s" ...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelinePar::setDelay(%lu): to %lu;"
	    "\tsetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulDelay, m_pSourceElement->m_ulDelay,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 
 
	// /XXXEH- TODO: figure out if we need to claim this is being set by
	// "parent" (which is really time base) so clip-begin-like action can
	// occur; I don't think so, however:
	m_pDependent->setDelay(ulTotalDelay, FALSE);
    }
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

    //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025:
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void
CSmilTimelinePar::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
				  BOOL bDurationExtendingDueToPause)
{
    if (bDurationExtendingDueToPause)
    {
	// /Need to handle this case:
	HX_ASSERT(!bDurationExtendingDueToPause);
    }
    setParExclDuration(ulDuration, bSetFromParent);
}

void
CSmilTimelinePar::setMaxDuration(UINT32 ulMaxDuration)
{
    setParExclMaxDuration(ulMaxDuration);
}

void 
CSmilTimelinePar::resetDelay(UINT32 ulDelay)
{
    INT32 lAdjustedDelay = 0;

    UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
	m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }

    if(m_pChildren)
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
	    pElement->resetDelay(m_pSourceElement->m_ulDelay);
	}
    }

    // /To fix PR 59851, we need to update our next-in-seq (m_pDependent) as
    // well as make sure sync-arc listeners know we've changed our overall
    // time bounds delay as well;
    if (m_pDependent && m_bDurationSet  &&
	    ulPriorDelay != m_pSourceElement->m_ulDelay)
    {
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
        if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(media version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><ref begin="1s" .../><ref begin="1s" .../>...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}
 
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelinePar::resetDelay(%lu):from %lu to %lu;"
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 
 
	m_pDependent->resetDelay(ulTotalDelay);
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

	// /(Added while fixing PR 59851) Let others know our begin time changed:
	m_pParser->m_pTimelineElementManager->notify(m_pID);
    }
}

void 
CSmilTimelinePar::adjustDuration()
{
    BOOL    bReset = FALSE;
    UINT32  ulDuration = 0;
    BOOL    bDurationSet = FALSE;
    BOOL    bEndsyncIdDurationFound = FALSE; // /For endsync="[Some ID]"
    // /Need this for fixing PR 50676 part 6:
    ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

    if (!m_bDurationSet)
    {
	goto cleanup;
    }

    if(m_pChildren)
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);

	    // /Checking this fixes PR 69290: if child duration wasn't set,
	    // then for crying out loud don't use it here:
	    if (!pElement->m_bDurationSet)
	    {
		continue;
	    }
	    HX_ASSERT((UINT32)-1 != pElement->m_pSourceElement->m_ulDuration);

	    // /Make sure we take endsync into account here; doing so helps fix
	    // PR 50679 (and probably other bugs):
	    if (SMILEventSourceFirst == m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (!bDurationSet)
		{
		    ulDuration = pElement->m_pSourceElement->m_ulDuration;
		}
		else
		{
    		    ulDuration = (ulDuration < pElement->m_pSourceElement->m_ulDuration) ?
			    ulDuration : pElement->m_pSourceElement->m_ulDuration;
		}
		bDurationSet = TRUE;
	    }
	    else if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (pElement->m_pSourceElement->m_pNode  &&
			m_pSourceElement->m_EndsyncEventSourceID ==
			pElement->m_pSourceElement->m_pNode->m_id)
		{
		    ulDuration = pElement->m_pSourceElement->m_ulDuration;
		    bEndsyncIdDurationFound = TRUE;
		    bDurationSet = TRUE;
		}
	    }
	    // /This else-if block fixes problem in PR 62688 repro case where
	    // restarting a child, prior to all children playing, caused excl
	    // to resolve its dur as if it were endsync="last":
	    else if (SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (m_pChildren  &&
			m_nDurationAdded >= m_pChildren->GetCount())
		{
    		    ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
			    ulDuration : pElement->m_pSourceElement->m_ulDuration;
		    bDurationSet = TRUE;
		}
		else
		{
		    // /Don't adjust duration until all child durs are in:
		    goto cleanup;
		}
	    }
	    else // /For "last", use the largest child duration:
	    {
		ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
			ulDuration : pElement->m_pSourceElement->m_ulDuration;
		bDurationSet = TRUE;
	    }

	    // /Fixes PR 50806 (original par version, INTEROP Timing #23.6 as
	    // well as par version 2 (endsync="last")): if this has a "min"
	    // attribute set, ulDuration shouldn't be less regardless of endSync:
	    if (m_pSourceElement->m_ulMinActiveDur > ulDuration)
	    {
		ulDuration = m_pSourceElement->m_ulMinActiveDur;
	    }
	}

	// /!bDurationSet happens in PR 50588 (case 2: begin="x.end"), when
	// child has begun playing but has not yet resolved its duration:
	if (!bDurationSet)
	{
	    goto cleanup;
	}

	if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
	{
	    if (!bEndsyncIdDurationFound)
	    {
		goto cleanup; // /That id'd child not added to timeline yet.
	    }
	}
//check m_ulAuthoredDur here:
	if (!m_pSourceElement->m_bHasExplicitEnd  &&
		!m_pSourceElement->m_bHasExplicitDur)
	{
	    m_pSourceElement->m_ulDuration = ulDuration;
	}
    
	// /Moved this out of the above if() so it gets called every time, to
	// fix PR 6XXX? and re-fix PR 55117: we should always give our parents
	// a chance to set the outer-time-container duration so it can (re)-
	// state to the core what the group duration should be:
	if(m_pParent)
	{
	    m_pParent->adjustDuration();
	}

	// /Moved this out to happen all the time, too:
	if (m_pDependent)
	{
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	    ULONG32 ulTotalDelay = 0;
	    if (HXR_OK !=
		    m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	    {
		goto doneSettingDependent;
	    }
#else
	    ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		    m_pSourceElement->m_ulDuration;
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/    		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase !=(UINT32)-1)
		{
		    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay);
		    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay)
		    {
			ulTotalDelay -=
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		    }
		}
	    }
#endif
	    if (WAY_IN_THE_FUTURE < ulTotalDelay)
	    {
		// /XXXEH- If delay is greater than this, I want to know:
		HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay);
		ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	    }

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
{
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE :
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
    ::fprintf(f1, "\n\t%s:CSmilTimelinePar::adjustDuration();\tresetting dependent (%s)'s delay to %lu\n",
	    (const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1);
    bFirstTimeAddDurDebugout = FALSE;
}
#endif
	    m_pDependent->resetDelay(ulTotalDelay);
	}
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
	;
#endif

    }

    // /Fixes PR 69410 (with outer par): do this no matter what, even if
    // prior < ulDur; resumed element in excl descendant should extend that
    // excl but we've already told the core to limit the presentation
    // duration, so extend it here as needed:
    // /Helps fix PR 50676 part 6: if our duration got reduced, we need to
    // possibly constrain our children:
    {
	// /For PR 62688 & PR 59584: remove check for ulPriorDuration being
	// WAY_IN_THE_FUTURE since PR 50676 works without it and there are
	// cases where our dur may re-resolve, & updating children is needed.

	// /For PR 59584: the group's outer time container needs to set the
	// duration if its dur is longer than its group's so far:
	if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	{
	    if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
		    m_pSourceElement->m_pNode->m_pParent->m_tag  ||
		    m_pSourceElement->m_pNode->
		    m_pParent->m_bIsOuterWrapperTimeContainer) )
	    {
		BOOL bDoResolveGroupDur = TRUE;
		UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
		if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
		{
		    ulGroup = 0;
		    // /If we're outer wrapper around multiple groups
		    // (or "clips"), then let each group outer time container
		    // resolve its group duration:
		    if (m_pChildren->GetCount() > 1)
		    {
			bDoResolveGroupDur = FALSE;
		    }
		}
		if (bDoResolveGroupDur)
		{
		    // /The group duration should be the duration of this
		    // outer-most time container:
		    HX_RESULT pnrs = m_pSourceElement->m_pHandler->
			    resolveGroupDurToOuterTimeContainerDur(
			    ulGroup, m_pSourceElement->m_ulDuration);
		}
	    }
	}
	if(m_pChildren)
	{
	    // /Accounting for begin offset of this helps fix PR 65741(par)
	    // where excl w/begin="5s' was including that 5s in dur passed
	    // to children, thus children were playing 5s too long:
	    ULONG32 ulSyncBaseDurationForChildren =
		    m_pSourceElement->m_ulDuration;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(ulSyncBaseDurationForChildren >=
			m_pSourceElement->m_ulBeginOffsetFromSyncBase);
		if (ulSyncBaseDurationForChildren >=
			m_pSourceElement->m_ulBeginOffsetFromSyncBase)
		{
		    ulSyncBaseDurationForChildren -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }

	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    for(; i != m_pChildren->End(); ++i)
	    {
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
		if (pElement->m_pSourceElement  &&
			pElement->m_pSourceElement->m_ulDuration >
			m_pSourceElement->m_ulDuration)
		{
		    pElement->setDuration(ulSyncBaseDurationForChildren, TRUE);
		}
	    }
	}
    }

cleanup:

    m_pParser->m_pTimelineElementManager->notify(m_pID);

    return;
}

void 
CSmilTimelinePar::addDuration(UINT32 ulDuration,
			      UINT32 ulDelay,
			      UINT32 ulChildDelayBeyondStartOfThis, 
			      const char* pElementID)
{
    BOOL bHandled = FALSE;

    UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelinePar{%s}::addDuration(dur=%lu, delay=%lu, "
		"childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sE\n",
		(const char*)m_pID, ulDuration, ulDelay,
		ulChildDelayBeyondStartOfThis, pElementID,
		m_bDurationSet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    // /If we're inside a seq, our true "sync base" is not the seq but rather
    // the prievious seq sibling (if any).  We need to adjust the ulDelay, if
    // we're in a seq, down to just ulChildDelayBeyondStartOfThis, which is
    // the delay from the prior sibling, not from the seq:
    ULONG32 ulDelayBeyondSyncBase = 0;
    SMILNode* pSyncBaseNode = NULL;
    if (m_pSourceElement->m_pNode)
    {
	pSyncBaseNode = m_pParser->getSyncAncestor(
	    m_pSourceElement->m_pNode);
    }
    if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
    {
	HX_ASSERT(pSyncBaseNode  &&  pSyncBaseNode->m_pElement);
    }
    // /Do this for all time containers (for part of PR52110 post-fix-delay-
    // offset-bug):
    else
    {
	ulDelayBeyondSyncBase = ulChildDelayBeyondStartOfThis;
    }

    BOOL bSetChildCurEndClippedByParent = FALSE;
    BOOL bSetCompletelyRemovedFromTimeline = FALSE;
    BOOL bIsCurChildsFirstAddDuration = FALSE;
    ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
    if (!(*m_pChildDurAddedMap)[pElementID])
    {
	bIsCurChildsFirstAddDuration = TRUE;
    }
    else
    {
	ulCurChildPriorAddedDuration =
		(ULONG32)((*m_pChildDurAddedMap)[pElementID]);
    }

    ULONG32 ulActualDurBeyondSyncBase =
	    ulDuration + ulDelayBeyondSyncBase - ulChildDelayBeyondStartOfThis;

// /XXXEH-20020106-test:    HX_ASSERT(WAY_IN_THE_FUTURE >= ulActualDurBeyondSyncBase);

    // /Start of fix for PR 55117: explicit dur or end on par should not be
    // overridden by some punk child's dur; if this has an explicit
    // end or dur, don't do anything to its duration based on children durs:
    // /XXXEH- TODO: determine what wins between endsync VS either end or dur
    // if both are specified; here, I assume end|dur wins over endsync:
    if (m_pSourceElement->m_bHasExplicitDur  ||
	    m_pSourceElement->m_bHasExplicitEnd)
    {
	if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
		(!m_bDurationSet  ||
		!m_pSourceElement->m_bAddDurationAlreadyDone) )
	{
	    HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
	    HX_ASSERT(m_pSourceElement->m_ulDuration ==
		    m_pSourceElement->getPureDuration());
	    durationResolved(m_pSourceElement->m_ulDuration, FALSE);
	}
	// /Helps fix PR 6XXXZ (PR 55117 revisited): par in seq where par has explicit dur and
	// children all have smaller durations, we need to give outer time
	// container a chance to hold the presentation open; this is needed
	// when this par is last one in presentation.  (Note: body doesn't set
	// the presentation time during createElements() phase because it
	// doesn't have m_pHandler yet then):
	adjustDuration();
	bHandled = TRUE;
    }
    // /Fixes SMIL 1.0's endsync="id(xyz)" and enables SMIL 2.0's
    // id-based endsync: endsync="xyz":
    else if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
    {
	if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
	        !strcmp(m_pSourceElement->m_EndsyncEventSourceID,pElementID))
	{
	    HX_ASSERT(m_pSourceElement->m_ulDuration ==
		    m_pSourceElement->getPureDuration());
	    // /Don't just use ulDuration in case child has a begin offset
	    // or otherwise has a delay beyond this's delay.
	    m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
	    durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    bHandled = TRUE;
	}
	// /Fixes endsync="[ID]" part of PR 59584 where addDuration of X (!=ID)
	// happens after that of lower-duration [ID] sibling and 'X' needs to
	// be restricted to ID's duration:
	else if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
	        m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
	{
	    // /Adjust for offset from parent, if any:
	    bSetChildCurEndClippedByParent = TRUE;
	    if (m_pSourceElement->m_ulDuration >
		    ulChildDelayBeyondStartOfThis)
	    {
		m_pParser->resetTimelineElementDuration(pElementID,
			m_pSourceElement->getPureDuration(),
			// /Changed to *child* prior dur while fixing PR 66391:
			ulActualDurBeyondSyncBase -
			ulChildDelayBeyondStartOfThis);
		m_pParser->m_pTimelineElementManager->notify(pElementID);
	    }
	    else // /Begin offset is beyond parent's end, so remove it:
	    // /Fixes PR 64158 (endsync="[ID]" version)
	    {
		bSetCompletelyRemovedFromTimeline = TRUE;
		HX_RESULT retval2 = m_pSourceElement->m_pHandler->
			handleTrackRemoval((const char*)pElementID,
			(INT32)m_pSourceElement->m_pNode->m_nGroup);
	    }
	}
    }
    else if(m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceAll)
    {
	// /Hold par open until all children have had a chance to begin;
	// leave the par's duration unresolved awaiting the final child's
	// call to "addDuration" (which may never come if child's begin
	// never resolves):

	// /Helps fix PR 62688(par version): first, check if all children
	// have resolved already; if so, then duration is set so we can't
	// extend it if begin is after parent par ended:
	if (m_nDurationAdded >= m_pChildren->GetCount()  &&
		m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
	{
	    bSetChildCurEndClippedByParent = TRUE;
	    HX_ASSERT(m_ulLastDuration == m_pSourceElement->m_ulDuration);
	    if (m_ulLastDuration > ulChildDelayBeyondStartOfThis)
	    {
		// /Helps fix PR 50660 by removing PR 62688-fix code here that
		// turned out to be unnecessary since code elsewhere completely
		// fixes PR 62688.  Child should be allowed to extend its
		// parent's duration except if it begins *after* its parent has
		// already ended, which is how we got here, so do nothing.
	    }
	    else // /Begin offset is beyond parent's end, so remove it:
	    // helps fix PR 62688(par) (endsync="all" version of PR 64158)
	    {
		bSetCompletelyRemovedFromTimeline = TRUE;
		HX_RESULT retval2 = m_pSourceElement->m_pHandler->
			handleTrackRemoval((const char*)pElementID,
			(INT32)m_pSourceElement->m_pNode->m_nGroup);
	    }
	}

	if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
		!m_bFirstDurationHasBeenSet)
	{
	    m_ulFirstDuration = ulActualDurBeyondSyncBase;
	    m_bFirstDurationHasBeenSet = TRUE;
	}
	if(ulActualDurBeyondSyncBase > m_ulLastDuration)
	{
	    m_ulLastDuration = ulActualDurBeyondSyncBase;
	}
	// /This helps fix PR 62688(par version): this is used to see if
	// we've already resolved our duration (because all children have
	// weighed in):
	INT32 lTotalDurationsAddedIncludingThisOne = (INT32)m_nDurationAdded;
	if (bIsCurChildsFirstAddDuration)
	{
	    lTotalDurationsAddedIncludingThisOne++;
	}
	if (lTotalDurationsAddedIncludingThisOne < m_pChildren->GetCount()  &&
		// /To help fix PR 59584(par version), only do this once:
		WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
	{
	    // /XXXEH- need a better way, but for now let's say it's
	    // resolved to a very big number until all children have
	    // resolved begins:
	    durationResolved(WAY_IN_THE_FUTURE, TRUE);
	}
    }
    else if(m_pSourceElement->m_ulDuration == (UINT32)-1)
    {
	// /Added delay to duration which works in:
	// "BUG-20010430_endHappening2sTooEarlyForExclThatHas"...
	// ..."2.7sBeginAndDurBasedOnChild(totalPresentationDur5.7s).smil":
	m_pSourceElement->m_ulDuration = ulDuration + ulDelayBeyondSyncBase -
		// /Added this to fix when par child of seq has child w/begin
		// offset, as in the following smil file:
		// "BUG-20010501_(broke20010501earlyAMCheckin)beginOnFirst"...
		ulChildDelayBeyondStartOfThis;

	m_ulFirstDuration = ulActualDurBeyondSyncBase;
	m_bFirstDurationHasBeenSet = TRUE;
	m_ulLastDuration = ulActualDurBeyondSyncBase;
    }
    else
    {
	m_pSourceElement->m_ulDuration = 
	    (ulActualDurBeyondSyncBase > m_pSourceElement->m_ulDuration) ?
	    ulActualDurBeyondSyncBase : m_pSourceElement->m_ulDuration;
	if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
		// /Fixes several PRs related to endsync="first"; m_ulFirstDuration
		// gets init'd to 0, so we need to see if it's been set or not:
		!m_bFirstDurationHasBeenSet)
	{
	    m_ulFirstDuration = ulActualDurBeyondSyncBase;
	    m_bFirstDurationHasBeenSet = TRUE;
	}
	if(ulActualDurBeyondSyncBase > m_ulLastDuration)
	{
	    m_ulLastDuration = ulActualDurBeyondSyncBase;
	}
    }

    ULONG32 ulRevisedActualDurBeyondSyncBase = ulActualDurBeyondSyncBase;
    if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceFirst)
    {
	// /Helps fix PR 66391: if child is time container, make sure this's
	// duration is set to shortest child's duration:
	m_pSourceElement->m_ulDuration = m_ulFirstDuration;

	// /Fixes endsync="first" version of PR 64157 where addDuration
	// of longer vid happens after that of lower-duration sibling and
	// longer one needs to be clipped to that lower duration (or completely
	// removed if begin offset is beyond parent's end (PR 64158)):
	if (m_bFirstDurationHasBeenSet  &&
		m_ulFirstDuration < ulActualDurBeyondSyncBase)
	{
	    bSetChildCurEndClippedByParent = TRUE;
	    if (m_ulFirstDuration > ulChildDelayBeyondStartOfThis)
	    {
		m_pParser->resetTimelineElementDuration(pElementID,
			m_ulFirstDuration -
			// /Fixes PR 64160 (ensync="first" version):
			ulChildDelayBeyondStartOfThis,
			// /Changed to *child* prior dur while fixing PR 66391:
			ulActualDurBeyondSyncBase -
			ulChildDelayBeyondStartOfThis);
		
		// /Update dur to be used:
		ulRevisedActualDurBeyondSyncBase = m_ulFirstDuration -
			ulChildDelayBeyondStartOfThis;
		m_pParser->m_pTimelineElementManager->notify(pElementID);
	    }
	    else // /Begin offset is beyond parent's end, so remove it:
	    // /Fixes PR 64158 (endsync="first" version)
	    {
		bSetCompletelyRemovedFromTimeline = TRUE;
		HX_RESULT retval2 = m_pSourceElement->m_pHandler->
			handleTrackRemoval((const char*)pElementID,
			(INT32)m_pSourceElement->m_pNode->m_nGroup);
	    }
	}
    }

    if (!(*m_pChildDurAddedMap)[pElementID])
    {
	m_nDurationAdded++;
	(*m_pChildDurAddedMap)[pElementID] = (void*)ulRevisedActualDurBeyondSyncBase;
    }
    ULONG32 ulChildrenCount = m_pChildren->GetCount();
    // /Fixes PR 56481 find children of this par that don't have a scheduled
    // begin, i.e., are awaiting an event to begin.  endsync="last" says to
    // ignore any children that never play, and we don't know if those
    // event-based begin children will play or not so ignore them for now,
    // and if they ever do begin, *then* re-compute this par's duration:
    ULONG32 ulNonEventBasedBeginChildCount = 0;
    CSmilElement* pCurChildElem = NULL;
    CHXSimpleList::Iterator i = m_pChildren->Begin();
    for(i; i != m_pChildren->End(); ++i)
    {
	CSmilTimelineElement* pTmlnElement =
		(CSmilTimelineElement*)(*i);
	if (pTmlnElement  &&  pTmlnElement->m_pSourceElement)
	{
	    BOOL isCurAddDurElem = FALSE;
	    if (!strcmp(pTmlnElement->m_pSourceElement->m_pNode->m_id,
		    pElementID))
	    {
		isCurAddDurElem = TRUE;
		pCurChildElem = pTmlnElement->m_pSourceElement;
		if (bSetChildCurEndClippedByParent  &&  pCurChildElem)
		{
		    pCurChildElem->m_bCurEndClippedByParent = TRUE;
		}
		if (bSetCompletelyRemovedFromTimeline  &&  pCurChildElem)
		{
		    pCurChildElem->m_bInsertedIntoTimeline = FALSE;
		}
	    }
	    if ((pTmlnElement->m_pSourceElement->
		    m_bHasAtLeastOneNonEventBasedBegin  ||
		    // /Do this so this par can re-resolve its duration if &
		    // when an event-based-begin child gets added (and thus
		    // technically now is a child with a clock-valued begin):
		    isCurAddDurElem) )
	    {
		ulNonEventBasedBeginChildCount++;
	    }
	}
    }
    
    if (!bHandled  &&
	    (m_nDurationAdded >= ulNonEventBasedBeginChildCount  &&
	    // /If endsync is all, we need to wait for *all* to be added:
	    (SMILEventSourceAll!=m_pSourceElement->m_nEndsyncEventSourceTag  ||
	    m_nDurationAdded == ulChildrenCount) )  &&
	    !m_bDurationEvent)
    {
	BOOL bUpdateDurMightBeNeeded = FALSE;
	// /Helps fix PR 62688(par): if duration was set before, but only to
	// hold the timeline open until all (or a particular) child duration
	// became known, then we want to ignore the durationSet flag so that
	// we call duartionResolved() instead of adjustDuration();
	BOOL bIgnoreDurationSetFlag = bIsCurChildsFirstAddDuration  &&
		(WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration);
	// /First, if duration has already been set, then pElement must be an
	// event-based-begin child that just resolved, so we need to reset
	// our duration appropriately:
	if (m_bDurationSet  &&  pCurChildElem  &&  !bIgnoreDurationSetFlag  &&
		!pCurChildElem->m_bHasAtLeastOneNonEventBasedBegin)
	{
	    bUpdateDurMightBeNeeded = TRUE;  // /(PR 59851 hits this line.)
	}

        // Switch on different endsync values
	if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceFirst)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulFirstDuration)
		{
		    // /XXXEH- revisit now that addDuration accts for endsync:
		    ULONG32 ulOldDur = m_pSourceElement->m_ulDuration;
		    adjustDuration();
		    HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulFirstDuration);
		    // /Other half of fix for PR 50679: if updated duration
		    // is less than prior dur, then update timeline element:
		    if (ulOldDur > m_pSourceElement->m_ulDuration)
		    {
			// /Reset duration-set flag to FALSE since we want to
			// override (reset) the dur now that this last child
			// has been resolved (presumably after playback of
			// this par began):
			m_bDurationSet = FALSE;
			HX_ASSERT(m_pSourceElement->m_ulDuration ==
				m_pSourceElement->getPureDuration());
			durationResolved(m_pSourceElement->m_ulDuration, TRUE);
		    }
		}
	    }
	    else
	    {
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		durationResolved(m_ulFirstDuration, TRUE);
	    }
	}
	else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceLast)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulLastDuration)
		{
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 62688(par version when endsync="last" is
		// explicitly declared): if we previously resolved our
		// duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    // /Fixes part 3 of PR 79699 (explicit endsync=last version)
		    // where it plays as indefinite because outer par wasn't
		    // adjusting for new non-indef dur:
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
			// /Trick adjustDuration() into doing its thing
			// since this is last child being added for 1st time:
			m_bDurationSet = TRUE;
		    }
		    adjustDuration();
		    m_bDurationSet = FALSE;
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		// /To fix PR 59584(par w/event-ended child), w/"last"), use
		// m_pSourceE.'s dur, not m_ulLastDuration since latter may
		// be wrong if some elements stopped early
		durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    }
	}
	else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceAll)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulLastDuration)
		{
		    // /adjustDuration() assumes endsync=last which is OK
		    // since we've got all durations:
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 59584(simplified): if we previously resolved
		// our duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
			// /See "part 2 of PR 79699" below; don't want to mess
			// with this unless there's content that asserts here:
			HX_ASSERT(m_bDurationSet);
		    }
		    adjustDuration();
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		// /Reset duration-set flag to FALSE since we want to
		// override (reset) the dur now that this last child has been
		// resolved (presumably after playback of this par began):
		m_bDurationSet = FALSE;
		// /To fix PR 59584(par w/event-ended child), w/"all"), use
		// m_pSourceE.'s dur, not m_ulLastDuration since latter may
		// be wrong if some elements stopped early
		durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    }
	}
	else
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_pSourceElement->m_ulDuration)
		{
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 62688(par version): if we previously resolved
		// our duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    // /Fixes part 2 of PR 79699 (imlicit endsync=last version)
		    // where it plays as indefinite because outer par wasn't
		    // adjusting for new non-indef dur:
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			HX_ASSERT(WAY_IN_THE_FUTURE == m_ulLastDuration  ||  m_bDurationSet);
			// /Trick adjustDuration() into doing its thing
			// since this is last child being added for 1st time:
			m_bDurationSet = TRUE;
		    }
		    adjustDuration();
		    m_bDurationSet = FALSE;
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		durationResolved(m_pSourceElement->m_ulDuration, FALSE);
	    }
	}

	// /This if() block fixes PR 56686 (version 3) and
	// PR 61174 (version 3): if time container has longer dur than its
	// children and it is not a time-child of the <body>, then its dur
	// was never getting accounted for, but now the outer time container
	// sets the duration if its dur is longer than its group's so far;
	// outer time contnr can only be a par if body has multiple children:
	if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	{
	    // /XXXEH- handle <body><switch><par> and <body><a><par>
	    if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
		    m_pSourceElement->m_pNode->m_pParent->m_tag  ||
		    m_pSourceElement->m_pNode->
		    m_pParent->m_bIsOuterWrapperTimeContainer) )
	    {
		UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
		// /The group duration should be the duration of this
		// outer-most time container:
		HX_RESULT pnrs = m_pSourceElement->m_pHandler->
			resolveGroupDurToOuterTimeContainerDur(
			ulGroup, m_pSourceElement->m_ulDuration);
	    }
	}
    }
}

void
CSmilTimelinePar::elementResolved(CSmilTimelineElement* pEventElement)
{
    parExclElementResolved(pEventElement);
}

void
CSmilTimelinePar::durationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
{
    parExclDurationResolved(ulDuration, bUpdateChildren);
}

#if 0

#error: **HEY: if this code ever gets enabled, handle CSmilTimelineExcl as well:

void 
CSmilTimelinePar::setEndsync(EndsyncType eType, 
			     const char* pEndsyncID,
			     UINT32 ulEndsyncClockValue)
{
    m_eEndsyncType = eType;
    m_ulEndsyncClockValue = ulEndsyncClockValue;
    if(pEndsyncID)
    {
	m_pEndsyncID = new char[strlen(pEndsyncID)+1];
	strcpy(m_pEndsyncID, pEndsyncID); /* Flawfinder: ignore */
    }
}
#endif

/***************************************************************************/

/*
 * CSmilTimelineSeq methods
 */
CSmilTimelineSeq::CSmilTimelineSeq(CSmilElement* pSourceElement,
				   CSmilParser* pParser):
    CSmilTimelineElement(pSourceElement, pParser),
    m_nDurationAdded(0)
{
}

void 
CSmilTimelineSeq::addDuration(UINT32 ulDuration, 
			      UINT32 ulDelay,
			      UINT32 ulChildDelayBeyondStartOfItsSyncBase, 
			      const char* pID)
{
    HX_ASSERT(m_pChildren);

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineSeq{%s}::addDuration(dur=%lu, delay=%lu, "
		"childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sE\n",
		(const char*)m_pID, ulDuration, ulDelay,
		ulChildDelayBeyondStartOfItsSyncBase, pID,
		m_bDurationSet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    // /I don't think we want to/need to use ulChildDelay; it is > 0 in
    // "BUG-20010502_repeatedElementWithBeginOf3sAndEndOf15s.smil" but
    // that works (offset-wise) so no need to use ulChildDelay...:

    ULONG32 ulActualDurBeyondSyncBase = ulDuration;
    // /Fixes case where this seq has a begin offset from its parent and
    // doesn't have an explicit end or dur; the child being added here
    // ended up playing too short by the amount of this's begin offset:
    BOOL bDurationIncludesDelayBeyondSyncbase = FALSE;
    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
    {
	ulActualDurBeyondSyncBase +=
		m_pSourceElement->m_ulBeginOffsetFromSyncBase;
	bDurationIncludesDelayBeyondSyncbase = TRUE;
    }

    if (ulChildDelayBeyondStartOfItsSyncBase > 0)
    {
	// /Helps fix PR 6XXXX: be sure to account for child's delay beyond
	// its prior sibling in this seq, or the seq itself if no prior sib:
	ulActualDurBeyondSyncBase -= ulChildDelayBeyondStartOfItsSyncBase;
    }
    else
    {
	HX_ASSERT(0 == ulChildDelayBeyondStartOfItsSyncBase  &&
		"ehodge: negative delay in seq!?");
    }

    BOOL bIsCurChildsFirstAddDuration = FALSE;
    ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
    if (!(*m_pChildDurAddedMap)[pID])
    {
	bIsCurChildsFirstAddDuration = TRUE;
    }
    else
    {
	ulCurChildPriorAddedDuration =
		(ULONG32)((*m_pChildDurAddedMap)[pID]);
    }

    if(!m_bDurationSet)
    {
	if(m_pSourceElement->m_ulDuration == (UINT32)-1)
	{
	    m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
	    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
		    bDurationIncludesDelayBeyondSyncbase;
	}
	// /Helps fix PR 62688 and PR 59584: never go higher duration than
	// WAY_IN_THE_FUTURE so overall timeline doesn't further extend:
	else if (WAY_IN_THE_FUTURE == ulActualDurBeyondSyncBase  ||
		WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration)
	{
	    m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
	    if (m_pSourceElement->m_ulDelay > 0)
	    {
		if (m_pSourceElement->m_ulDuration >=
			m_pSourceElement->m_ulDelay)
		{
		    m_pSourceElement->m_ulDuration -=
			    m_pSourceElement->m_ulDelay;
		}
		else
		{
		    m_pSourceElement->m_ulDuration = 0;
		}
	    }
	    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
		    bDurationIncludesDelayBeyondSyncbase;
	}
	else
	{
	    m_pSourceElement->m_ulDuration += ulActualDurBeyondSyncBase;
	    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
		    bDurationIncludesDelayBeyondSyncbase;
	}
    }
    // /Fixes unfiled(?) bug found when PR 52110 was fixed: seq with begin
    // offset>0 and explicit dur was not accounting for this offset in its
    // duration, but parent's addDuration() counts on that being done:
    else if (m_pSourceElement->m_bHasExplicitDur  &&
	    !m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
    {
	if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
	{
	    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
		    bDurationIncludesDelayBeyondSyncbase;
	    m_pSourceElement->m_ulDuration +=
		    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
	}
    }

    if (!(*m_pChildDurAddedMap)[pID])
    {
	m_nDurationAdded++;
	(*m_pChildDurAddedMap)[pID] = (void*)ulActualDurBeyondSyncBase;
    }
    if(m_nDurationAdded == m_pChildren->GetCount()  ||
	    // /Helps fix PR 59584: if our dur is unresolved, then we need to
	    // notify our parent (and on up the chain) that there is an
	    // currently-indefinite-duration element in the presentation:
	    WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDuration +
	    m_pSourceElement->m_ulDelay)
    {
	m_bDurationSet = TRUE;
	if (m_nDurationAdded == m_pChildren->GetCount())
	{
	    // /We need to adjust our duration in case it was temporarily set
	    // to indefinite; now that we have all children accounted for, we
	    // can correctly calculate it:  (fixes PR 59584 overall duration)
	    adjustDuration();
	}
        // Add our duration to our parent
	if(m_pParent)
	{
	    ULONG32 ulDelayFromSyncBaseBegin = 0;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
	    {
		ulDelayFromSyncBaseBegin =
			m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		// /Fixes PR 68875: be sure to add offset from syncbase if
		// not already included:
		if ((UINT32)-1 != ulDelayFromSyncBaseBegin
			&&  ulDelayFromSyncBaseBegin > 0  &&
			!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
		{
		    m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase = TRUE;
		}
	    }
	    m_pParent->addDuration( 
		    m_pSourceElement->m_ulDuration, 
		    m_pSourceElement->m_ulDelay,
		    ulDelayFromSyncBaseBegin, m_pID);
	    m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
	}

	// /This if() block fixes PR 56686 (version 2) and
	// PR 61174 (version 2): if time container has longer dur than its
	// children and it is not a time-child of the <body>, then its dur
	// was never getting accounted for, but now the outer time container
	// sets the duration if its dur is longer than its group's so far:
	if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	{
	    if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
		    m_pSourceElement->m_pNode->m_pParent->m_tag  ||
		    m_pSourceElement->m_pNode->
		    m_pParent->m_bIsOuterWrapperTimeContainer) )
	    {
		BOOL bDoResolveGroupDur = TRUE;
		UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
		if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
		{
		    ulGroup = 0;
		    // /If we're outer seq wrapper around multiple groups
		    // (or "clips"), then let each group outer time container
		    // resolve its group duration:
		    if (m_pChildren->GetCount() > 1)
		    {
			bDoResolveGroupDur = FALSE;
		    }
		}
		if (bDoResolveGroupDur)
		{
		    // /The group duration should be the duration of this
		    // outer-most time container:
		    HX_RESULT pnrs = m_pSourceElement->m_pHandler->
			    resolveGroupDurToOuterTimeContainerDur(
			    ulGroup, m_pSourceElement->m_ulDuration);
		}
	    }
	}



        // Now we know the duration of this <seq>, so 
        // we need to check the fill behavior of all our
        // children
        checkChildrenFillBehavior();
	if(m_pDependent)
	{
	    HX_ASSERT(m_bDurationSet);
	    adjustDependentDuration(m_pDependent);

#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	    ULONG32 ulTotalDelay = 0;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	    }

	    if (HXR_OK !=
		    m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	    {
		goto doneSettingDependent;
	    }
#else
	    ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		    m_pSourceElement->m_ulDuration;
	    // /Helps fix PR 6XXXX(seq version): if delay is already packed
	    // into the duration, then don't count it twice (as can happen in
	    // <seq><seq begin="1s">...</seq><seq begin="1s" ...):
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
		{
		    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay);
		    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay)
		    {
			ulTotalDelay -=
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		    }
		}
	    }
#endif

	    if (WAY_IN_THE_FUTURE < ulTotalDelay)
	    {
		HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
		ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	    }

	    // /XXXEH- TODO: figure out if we need to claim this is being set
	    // by "parent" (which is really time base) so clip-begin-like
	    // action can occur; I don't think so, however:
	    m_pDependent->setDelay(ulTotalDelay, FALSE);	    
	}
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

	// /[SMIL 1.0 Compliance] Fixes PR 23779:
	// if a source has event-based timing based on this seq's
	// duration, then we need to notify that source that we've
	// resolved this value:
	m_pParser->m_pTimelineElementManager->notify(m_pID);
    }
}

void 
CSmilTimelineSeq::setDelay(UINT32 ulDelay,
	   // /NOTE: we ignore this in time containers that aren't media:
	   BOOL bSetByParent)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineSeq{%s}::setDelay(delay=%lu, "
		"bSetByParent=%sE) m_bDelaySet=%sE\n",
		(const char*)m_pID, ulDelay,
		bSetByParent?"TRU":"FALS",
		m_bDelaySet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	m_pSourceElement->m_ulDelay = (
		((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
		(UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }
    //XXXJHUG - we need to prevent overwriting the delay when
    // setInitalDelay is called on THIS element, changing this
    // bool causes initialDelaySet to return TRUE.
    m_bDelaySet = TRUE;
    if(m_pChildren && m_pChildren->GetCount() > 0)
    {
	// set delay on first child of seq
	CSmilTimelineElement* pElement = 
	    (CSmilTimelineElement*)m_pChildren->GetHead();
	pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);

	// /To fix it so second group plays (PR6XXX5) after fix for (PR6XXX4),
	// need to set the delay of all children since each is not dependent
	// on the prior; problem is that a child 'n' with an explicit dur will
	// (now) tell its parent its dur during the above setDelay() call and
	// that will end up with this->setDuration() call happening too early,
	// farther below, resulting in all groups > n getting a 0 duration:
	SMILNode* pSyncAncestor = m_pParser? m_pParser->getSyncAncestor(
		m_pSourceElement->m_pNode) : NULL;

	if (!pSyncAncestor  ||  (SMILBody == pSyncAncestor->m_tag  &&
		m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer) )
	{
	    // /Need to set the delays of all children to 0 since each starts its
	    // own "clip" (group):
	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    ++i;  // /Already done for group 0, above.
	    for(; i != m_pChildren->End(); ++i)
	    {
		pElement = (CSmilTimelineElement*)(*i);
		// /If 0 != this's delay, then body must have begin="x" on it
		// and subsequent groups should not include that delay:
		HX_ASSERT(0 == m_pSourceElement->m_ulDelay);
		pElement->setDelay(0, TRUE);
	    }
	}
    }

    // /Fixes PR 24046 (SMIL 2+ seq version): if there are no children,
    // then the seq's duration is zero, so set it to 0:
    else if (m_pSourceElement->m_ulDuration == (UINT32)-1)
    {
	m_pSourceElement->m_ulDuration = 0;
    }

    if (m_pSourceElement->m_ulDuration != (UINT32)-1)
    {
	setDuration(m_pSourceElement->m_ulDuration);

#if 0 /* 20011024 */
	// /Fixes seq version of PR 61174(version1) and PR 56686
	// (version1): we know our duration already, so let's declare it
	// resolved so we get added to our parent (in case none of our

// XXXNH: for some reason, despite being if-zeroed-out, this causes a compiler
// error on linux!
//#error: DUDE!?!: children of seq can't have unresolved begins!:	

        // children have scheduled begin times in which case our
	// ::addDuration() would not get called up front and the overall
	// presentation would not include our duration at first):
	if (m_pSourceElement->m_bHasExplicitDur  ||
		m_pSourceElement->m_bHasExplicitEnd)
	{
	    // /Be sure not to override a shorter duration that may have
	    // been imposed on us by our parent:
	    if (!m_bDurationSet  ||
		    !m_pSourceElement->m_bAddDurationAlreadyDone)
	    {
		HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);

		m_bDurationSet = TRUE;
		if (m_pParent)
		{
		    ULONG32 ulDelayFromSyncBaseBegin = 0;
		    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase)
		    {
			ulDelayFromSyncBaseBegin =
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
			if (ulDelayFromSyncBaseBegin > 0  &&
				!m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
			{
			    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase =
				    TRUE; // /=TRUE,not ULONG32. Helps fix PR 68190.
			    m_pSourceElement->m_ulDuration += ulDelayFromSyncBaseBegin;
			}
		    }
		    m_pParent->addDuration(m_pSourceElement->m_ulDuration,
			    m_pSourceElement->m_ulDelay,
			    ulDelayFromSyncBaseBegin, m_pID);
		    m_pSourceElement->m_bAddDurationAlreadyDone = TRUE;
		}
	    }
	    HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
	}
#endif
    }

    //[SMIL 1.0 Compliance] Helps fix PR 14420 and 23025:
    // if a source has event-based timing based on this seq's
    // begin time (delay) then we need to notify that source
    // that we've resolved this value:
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void
CSmilTimelineSeq::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
				  BOOL bDurationExtendingDueToPause)
{
    ASSERT(m_pChildren  ||  0==ulDuration);

    if (bDurationExtendingDueToPause)
    {
	// /Need to handle this case:
	HX_ASSERT(!bDurationExtendingDueToPause);
    }

    if(!m_bDurationSet  ||
	    // /Adding this fixes PR 27644 and other cases where explicit
	    // dur|end of parent was being ignored by explicit (and larger)
	    // dur|end of child seq.  This allows repeatDur to work when
	    // parent has explicit dur|end since repeatDur creates a seq
	    // with an explicit dur:
	    bSetFromParent)
    {
	m_pSourceElement->m_ulDuration = ulDuration;
	m_bDurationSet = TRUE;
    }

    UINT32	ulDurationLeft = m_pSourceElement->m_ulDuration;
    RepeatTag	repeatTag = RepeatUnknown;

    if (m_pChildren) // /Fixes crash in case of a "<seq></seq>" (PR 65069).
    { 
	CHXSimpleList::Iterator i = m_pChildren->Begin(); 
	for(; i != m_pChildren->End(); ++i) 
	{ 
	    CSmilTimelineElement* pTmLnElement = (CSmilTimelineElement*)(*i); 
	    CSmilElement* pElement = pTmLnElement->m_pSourceElement;
	    if (!setElementDuration(ulDurationLeft, pTmLnElement))
	    {
		break;
	    }

	    // /Fixes PR 99498: make sure m_pSourceElement's time values are
	    // in same time-coords as pElement's before comparing the two;
	    // in this bug, a seq that began at 15s (15000 delay) had a
	    // duration that did not include that delay so the below PR 66391
	    // fix's if() was erroneously evaluating to true, thus ending
	    // this's children early.  Use this's soureElement's dur+delay,
	    // not its m_ulDuration (which may or may not include delay):
	    UINT32 ulDurationPlusDelayOfThisSeq =
		    m_pSourceElement->getPureDuration() +
		    m_pSourceElement->m_ulDelay;

	    // /Helps fix PR 66391: if this's m_ulDuration has shortened and
	    // its child(ren)'s duration is shortened to zero as a result,
	    // then remove child track if it begins too late to ever play:
	    if (pElement  &&  pElement->m_pHandler  &&
		    pElement->m_ulDelay > ulDurationPlusDelayOfThisSeq  &&
		    pElement->m_bInsertedIntoTimeline)
	    {
		pElement->m_bCurEndClippedByParent = TRUE;

		HX_ASSERT(0 == ulDurationLeft);
		BOOL bCurElementIsTimeContainer =
			m_pParser->isTimeContainerObject(pElement->m_pNode);
		HX_ASSERT(!bCurElementIsTimeContainer  &&  "ehodge:handle_removing_grandkids");

		HX_RESULT retvl = pElement->m_pHandler->handleTrackRemoval(
			(const char*)pElement->m_pNode->m_id,
			(INT32)pElement->m_pNode->m_nGroup);
		if (HXR_OK == retvl)
		{
		    // /Notify syncArc dependents that it ended early:
		    m_pParser->m_pTimelineElementManager->notify((const char*)pElement->m_pNode->m_id);
		}
	    }
	} 
    } 

    if(m_pDependent)
    {
	HX_ASSERT(m_bDurationSet);

	adjustDependentDuration(m_pDependent);	

#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
        if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(seq version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><seq begin="1s">...</seq><seq begin="1s" ...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}

	// /XXXEH- TODO: figure out if we need to claim this is being set
	// by "parent" (which is really time base) so clip-begin-like
	// action can occur; I don't think so, however:
	m_pDependent->setDelay(ulTotalDelay, FALSE);
    }
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

    //[SMIL 1.0 comliance] Helps fix PR 14420 and 23025:
    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void
CSmilTimelineSeq::setMaxDuration(UINT32 ulMaxDuration)
{
    HX_ASSERT(m_pChildren);
    m_bMaxDurationSet = TRUE;
    m_pSourceElement->m_ulMaxDuration = ulMaxDuration;

    if (m_pChildren  &&  m_bDelaySet)
    {
	HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);

	CSmilTimelineElement* pElement = (CSmilTimelineElement*)m_pChildren->GetHead();
	pElement->setMaxDuration(ulMaxDuration);
    }
}

void 
CSmilTimelineSeq::adjustDependentDuration(CSmilTimelineElement* pDependent)
{
    if(m_bDurationSet || m_bMaxDurationSet)
    {
	UINT32	    ulDurationLeft = m_bDurationSet?m_pSourceElement->m_ulDuration:
						    m_pSourceElement->m_ulMaxDuration;
	UINT32 ulOriginalDurationLeft = ulDurationLeft;
	if (m_pSourceElement->m_ulMinActiveDur>ulDurationLeft)
	{
	    ulDurationLeft = m_pSourceElement->m_ulMinActiveDur;
	}
	BOOL	    bAdjusted = FALSE;
	RepeatTag   repeatTag = RepeatUnknown;

	if (m_pChildren) // /Fixes crash in case of a "<seq></seq>" (PR 65069).
	{ 
	    CHXSimpleList::Iterator i = m_pChildren->Begin(); 
	    for(; i != m_pChildren->End(); ++i) 
	    { 
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i); 
		UINT32 ulChildDuration = pElement->getDuration(); 
 
		if (pElement == pDependent) 
		{ 
		    bAdjusted = TRUE; 
		} 
 
		if (bAdjusted) 
		{ 
		    if (pElement->getDelay() != (UINT32)-1)
		    {
			HX_ASSERT(pElement->getDelay() < WAY_IN_THE_FUTURE  &&
			    "need to reset delay b4 dur!");
		    }
		    // /Fixes PR 59584(parFollowsPar version):  If seq has
		    // unresolved-dur child, don't set dur of next sibling
		    // if it doesn't have delay set yet:
		    else if (0 == ulDurationLeft  &&  WAY_IN_THE_FUTURE ==
			    ulOriginalDurationLeft)
		    {
			break; // /Don't do anything.
		    }
		    // /Helps fix full repro case of PR 59584: second par
		    // in seq will have delay>0 and interim duration
		    // of WAY_IN_THE_FUTURE *minus* delay:
		    if (WAY_IN_THE_FUTURE <= ulOriginalDurationLeft)
		    {
			ulDurationLeft = WAY_IN_THE_FUTURE;
			setElementDuration(ulDurationLeft, pElement);
			break; // /Go no further for now.
		    }
		    if (!setElementDuration(ulDurationLeft, pElement)) 
		    { 
			break; 
		    } 
		} 
		else 
		{ 
		    if(ulDurationLeft >= ulChildDuration) 
		    { 
			ulDurationLeft -= ulChildDuration; 
		    } 
		    else 
		    { 
			ulDurationLeft = 0; 
		    } 
		} 
	    } 
	} 

	if (!bAdjusted && m_pParent)
	{
	    m_pParent->adjustDependentDuration(pDependent);
	}
    }
}

void 
CSmilTimelineSeq::resetDelay(UINT32 ulDelay)
{
    INT32 lAdjustedDelay = 0;

    UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
	m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }

    if(m_pChildren && m_pChildren->GetCount() > 0)
    {
	// set delay on first child of seq
	CSmilTimelineElement* pElement = 
	    (CSmilTimelineElement*)m_pChildren->GetHead();
#if 200110241
	if (m_pSourceElement->m_ulDelay !=
		pElement->m_pSourceElement->m_ulDelay)
	{
	    pElement->resetDelay(m_pSourceElement->m_ulDelay);
	}
#else
	pElement->resetDelay(m_pSourceElement->m_ulDelay);
#endif
    }

    // /To fix PR 59851(seq of seqs), we need to update our next-in-seq
    // (m_pDependent) as well as make sure sync-arc listeners know we've
    // changed our overall time bounds delay as well;
    if (m_pDependent && m_bDurationSet  &&
	    ulPriorDelay != m_pSourceElement->m_ulDelay)
    {
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
        if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif
	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}
 
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelineSeq::resetDelay(%lu):from %lu to %lu;"
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 
 
	m_pDependent->resetDelay(ulTotalDelay);
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

	// /(Added while fixing PR 59851) Let others know our begin time changed:
	m_pParser->m_pTimelineElementManager->notify(m_pID);
    }
}

void 
CSmilTimelineSeq::adjustDuration()
{
    UINT32  ulDuration = 0;

    // /Fixes seq version of PR 50676 (Added during fix for PR 59584):
    ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

    if (m_pChildren)
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
	    if ((UINT32)-1 == pElement->m_pSourceElement->m_ulDuration)
	    {
		// /Helps fix PR 59584 (parFollowsPar version): if child dur
		// is not resolved yet, then we're unresolved:
		ulDuration = WAY_IN_THE_FUTURE;
		break;
	    }
	    ulDuration += pElement->m_pSourceElement->m_ulDuration;
	    // /For PR 59584: don't go past "unresolved" dur value:
	    if (ulDuration >= WAY_IN_THE_FUTURE)
	    {
		ulDuration = WAY_IN_THE_FUTURE;
		break;
	    }
	}

	if (!m_pSourceElement->m_bHasExplicitEnd  &&
		!m_pSourceElement->m_bHasExplicitDur)
	{
	    // /Use child durs only if seq doesn't have explicit end or dur;
	    // This helps fix PR 6XXXY:
	    m_pSourceElement->m_ulDuration = ulDuration;
	}

	if(m_pParent)
	{
	    m_pParent->adjustDuration();
	}

	// /Fixes PR 69410: need to do this no matter what, even if prior <
	// ulDur; resumed element in excl descendent should extend that excl
	// but we've already told the core to limit the presentation duration,
	// so extend it here as needed (also fixes part of PR 50660):
	// /(Added while fixing PR 59584): if our duration got reduced, we need to
	// possibly constrain the group's duration:
	{
	    // This group's outer time container, if this is one, needs
	    // to set the duration if its dur is longer than its group's so far
	    // or if its previous duration was unresolved and now is resolved:
	    if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	    {
		if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
			m_pSourceElement->m_pNode->m_pParent->m_tag  ||
			m_pSourceElement->m_pNode->
			m_pParent->m_bIsOuterWrapperTimeContainer) )
		{
		    BOOL bDoResolveGroupDur = TRUE;
		    UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
		    if (m_pSourceElement->m_pNode->m_bIsOuterWrapperTimeContainer)
		    {
			ulGroup = 0;
			// /If we're outer wrapper around multiple groups
			// (or "clips"), then let each group outer time container
			// resolve its group duration:
			if (m_pChildren->GetCount() > 1)
			{
			    bDoResolveGroupDur = FALSE;
			}
		    }
		    if (bDoResolveGroupDur)
		    {
			// /The group duration should be the duration of this
			// outer-most time container:
			HX_RESULT pnrs = m_pSourceElement->m_pHandler->
				resolveGroupDurToOuterTimeContainerDur(
				ulGroup, m_pSourceElement->m_ulDuration);
		    }
		}
	    }
	}

	if(m_pDependent)
	{
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	    ULONG32 ulTotalDelay = 0;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	    }

	    if (HXR_OK !=
		    m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	    {
		goto doneSettingDependent;
	    }
#else
	    ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		    m_pSourceElement->m_ulDuration;
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
		{
		    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay);
		    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay)
		    {
			ulTotalDelay -=
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		    }
		}
	    }
#endif
	    if (WAY_IN_THE_FUTURE < ulTotalDelay)
	    {
		HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
		ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	    }

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
{
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE :
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
    ::fprintf(f1, "\n\t%s:CSmilTimelineSeq::adjustDuration();\tresetting dependent (%s)'s delay to %lu\n",
	    (const char*)m_pID, (const char*)m_pDependent->m_pID,
	    ulTotalDelay);
    ::fclose(f1);
    bFirstTimeAddDurDebugout = FALSE;
}
#endif

	    m_pDependent->resetDelay(ulTotalDelay);
	}
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
	;
#endif

    }
}

BOOL
CSmilTimelineSeq::setElementDuration(UINT32& ulDurationLeft, CSmilTimelineElement* pElement)
{
    BOOL	bContinue = TRUE;
    UINT32	ulChildDuration = pElement->getDuration();	
    RepeatTag   repeatTag = pElement->m_pSourceElement->m_pNode->m_repeatTag;
	
    if (repeatTag == RepeatIndefiniteOnMe)
    {
	pElement->setMaxDuration(ulDurationLeft);
	ulDurationLeft = 0;
	goto cleanup;
    }
    else if (repeatTag == RepeatIndefiniteOnGroup)
    {
	pElement->setMaxDuration(ulDurationLeft);
	bContinue = FALSE;
	goto cleanup;
    }

    // no more duration left, take care of the duration of the rest of 
    // the elements
    if (0 == ulDurationLeft)
    {
	pElement->setDuration(ulDurationLeft, TRUE);
    }
    // if this is the last child, then enforce the duration whatever
    // left
    else if (pElement == m_pChildren->GetTail())
    {
	if (ulChildDuration == (UINT32)-1  &&
		ulDurationLeft >= WAY_IN_THE_FUTURE)
	{
	    // /Doing this instead of setDuration() fixes PR 65741 when outer
	    // seq gets held open due to tracks' durations setting in a
	    // certain order.  In this case, don't override possible child
	    // explicit dur or end:
	    pElement->setMaxDuration(ulDurationLeft);
	}
	else
	{
	    pElement->setDuration(ulDurationLeft, TRUE);
	}
	bContinue = FALSE;
    }
    // unknown duration, so we apply max. duration here
    else if (ulChildDuration == (UINT32)-1)
    {
	pElement->setMaxDuration(ulDurationLeft);
	bContinue = FALSE;
    }
    else	
    {
	if(ulDurationLeft >= ulChildDuration)
	{
	    ulDurationLeft -= ulChildDuration;
	}
	else
	{
	    pElement->setDuration(ulDurationLeft, TRUE);
	    ulDurationLeft = 0;
	}
    }

cleanup:

    return bContinue;
}

/***************************************************************************/

// /XXXEH- see if any or all of the following can be combined with
// CSmilTimelinePar methods, above (with added params for dealing
// with Excl in minor places):
/*
 * CSmilTimelineExcl methods
 */

CSmilTimelineExcl::CSmilTimelineExcl(CSmilElement* pSourceElement,
				   CSmilParser* pParser):
    CSmilTimelineElement(pSourceElement, pParser),
    m_nDurationAdded(0),
    m_ulFirstDuration(0),
    m_bFirstDurationHasBeenSet(FALSE),
    m_ulLastDuration(0)
{
}

CSmilTimelineExcl::~CSmilTimelineExcl()
{
}

void 
CSmilTimelineExcl::setDelay(UINT32 ulDelay,
	   // /NOTE: we ignore this in time containers that aren't media:
	   BOOL bSetByParent)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineExcl{%s}::setDelay(delay=%lu, "
		"bSetByParent=%sE) m_bDelaySet=%sE\n",
		(const char*)m_pID, ulDelay,
		bSetByParent?"TRU":"FALS",
		m_bDelaySet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	m_pSourceElement->m_ulDelay = (
		((INT32)ulDelay+m_pSourceElement->m_lBeginOffset > 0) ?
		(UINT32)((INT32)ulDelay+m_pSourceElement->m_lBeginOffset):0);
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }
    if (!m_bDelayEvent)
    {
	m_bDelaySet = TRUE;
	ULONG32 ulNumChildrenWithNonEventBasedBegins = 0;
	if(m_pChildren)
	{
	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    for(; i != m_pChildren->End(); ++i)
	    {
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
		// /Don't set delay of children with no valid begin time; the
		// default begin of an excl child is "indefinite".  Note that
		// sync-arc begins of elements that are skipped during this
		// delay-setting-by-parent operation will be OK when they
		// resolve because the resolved time has the delay built in:
		// /Note: tested this with <a> child and it works fine,
		if (pElement->m_pSourceElement  &&
			(pElement->m_pSourceElement->m_bBeginOffsetSet
#if defined(XXXEH_HANDLE_MULTIPLE_EXCL_CHILD_SCHEDULED_BEGINS)
 /*can't do this fix yet because excl child w/beginOffset>0 must wait*/
			// /If parent excl begins on event, child with non-
			// event begin time won't yet have beginOffsetSet;
			// fixes PR 56686(version 7 and 8):
			|| pElement->m_pSourceElement->
			m_bHasAtLeastOneNonEventBasedBegin) )
#else
			) )
#endif
		{
		    pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		}
		// /else leave delay unresolved.
		// /However, we need to go ahead and see which children have
		// non-event-based begins (see PR 24046 fix, below, which
		// this part of fix for PR 62688 broke by putting the
		// following code inside the if(), above (which never got hit
		// in an excl):
		// /This helps fix PR 62688(excl version):
		if (pElement->m_pSourceElement  &&
			pElement->m_pSourceElement->
			m_bHasAtLeastOneNonEventBasedBegin)
		{
		    ulNumChildrenWithNonEventBasedBegins++;
		}
	    }
	}
	// /Fixes PR 24046 (SMIL 2+ excl version): if there are no children,
	// then the excl's duration is zero, so set it to 0:
	if ((!m_pChildren  &&  m_pSourceElement->m_ulDuration == (UINT32)-1)  ||
		0 == ulNumChildrenWithNonEventBasedBegins)
	{
	    // /Checking 1st for explicit end or dur re-fixes PR 57150(excl)
	    // which was broken by fix for PR 24046 (note: PR 57150 has dur=x
	    // *and* endsync="all" which is a strange thing to author):
	    if (!m_pSourceElement->m_bHasExplicitDur  &&
		    !m_pSourceElement->m_bHasExplicitEnd)
	    {
		m_pSourceElement->m_ulDuration = 0;
	    }
	    // /Helps fix PR 62688(excl version): if all children are
	    // event-begun and there is at least one child, and endsync="all",
	    // then we have an indefinite duration until all child ends resolve:
	    if (m_pChildren  &&  SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag  &&
		    // /Ignore endsync if it has explicit end or dur:
		    !m_pSourceElement->m_bHasExplicitDur  &&
		    !m_pSourceElement->m_bHasExplicitEnd)
	    {
		m_pSourceElement->m_ulDuration = WAY_IN_THE_FUTURE;
	    }
	}

	if (m_pSourceElement->m_ulDuration != (UINT32)-1)
	{
	    setDuration(m_pSourceElement->m_ulDuration);

#if 20011024
	    // /Fixes PR 61174(version1) and excl version of PR 56686
	    // (version1): we know our duration already, so let's declare it
	    // resolved so we get added to our parent (in case none of our
	    // children have scheduled begin times in which case our
	    // ::addDuration() would not get called up front and the overall
	    // presentation would not include our duration at first):
	    if (m_pSourceElement->m_bHasExplicitDur  ||
		    m_pSourceElement->m_bHasExplicitEnd  ||
		    // /For PR 62688(excl version) and other endsync="all" bugs:
		    SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		// /Be sure not to override a shorter duration that may have
		// been imposed on us by our parent:
		if (!m_bDurationSet  ||
			!m_pSourceElement->m_bAddDurationAlreadyDone)
		{
		    HX_ASSERT(m_pSourceElement->m_ulDuration ==
			    m_pSourceElement->getPureDuration());
		    HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
		    durationResolved(m_pSourceElement->m_ulDuration, FALSE);
		}
		HX_ASSERT(m_bDurationSet  &&  m_pSourceElement->m_bAddDurationAlreadyDone);
	    }
#endif
	}
    }
    else 
	// /Let's not claim that the delay is set when we still
	// are awaiting a delay (begin) event; we *do* need to
	// add the delay of this to the event's begin offset.
	// This is done by setting the new "m_bNonEventDelaySet"
	// variable to TRUE and leaving m_bDelaySet to FALSE
	// until the ElementResolved() call sets it to true:
    {
	// /Parent calls setDelay before we get to ElementResolved,
	// thus m_bDelaySet should never be TRUE if we have a
	// delay event:
	HX_ASSERT(!m_bDelaySet);
	m_bNonEventDelaySet = TRUE; //ElementResolved will look at this.
	m_ulNonEventDelay = ulDelay;
    }
    
    if(m_pDependent && m_bDurationSet)
    {
	adjustDependentDuration(m_pDependent);

#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
	if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	// /Helps fix PR 6XXXX(excl version): if delay is already packed
	// into the duration, then don't count it twice (as can happen in
	// <seq><excl begin="1s">...</excl><excl begin="1s" ...):
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/	    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif

	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelineExcl::setDelay(%lu): to %lu;"
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulDelay, m_pSourceElement->m_ulDelay,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 
 
	// /XXXEH- TODO: figure out if we need to claim this is being set
	// by "parent" (which is really time base) so clip-begin-like
	// action can occur; I don't think so, however:
	m_pDependent->setDelay(ulTotalDelay, FALSE);
    }
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

    m_pParser->m_pTimelineElementManager->notify(m_pID);
}

void
CSmilTimelineExcl::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
				  BOOL bDurationExtendingDueToPause)
{
    if (bDurationExtendingDueToPause)
    {
	// /Need to handle this case:
	HX_ASSERT(!bDurationExtendingDueToPause);
    }

    setParExclDuration(ulDuration, bSetFromParent);
}

void
CSmilTimelineExcl::setMaxDuration(UINT32 ulMaxDuration)
{
    setParExclMaxDuration(ulMaxDuration);
}

void 
CSmilTimelineExcl::resetDelay(UINT32 ulDelay)
{
    INT32 lAdjustedDelay = 0;

    UINT32 ulPriorDelay = m_pSourceElement->m_ulDelay;

    if(m_pSourceElement->m_bBeginOffsetSet)
    {
	lAdjustedDelay = (INT32)ulDelay + m_pSourceElement->m_lBeginOffset;
	m_pSourceElement->m_ulDelay = lAdjustedDelay > 0?lAdjustedDelay:0;
    }
    else
    {
	m_pSourceElement->m_ulDelay = ulDelay;
    }

    if(m_pChildren)
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);

	    // /Don't set delay of children with no valid begin time; the
	    // default begin of an excl child is "indefinite".  Note that
	    // sync-arc begins of elements that are skipped during this
	    // delay-setting-by-parent operation will be OK when they
	    // resolve because the resolved time has the delay built in:
	    // /Note: tested this with <a> child and it works fine,
	    if (pElement->m_pSourceElement  &&
		    (pElement->m_pSourceElement->m_bBeginOffsetSet
#if defined(XXXEH_HANDLE_MULTIPLE_EXCL_CHILD_SCHEDULED_BEGINS)
 /*can't do this fix yet because excl child w/beginOffset>0 must wait*/
			// /If parent excl begins on event, child with non-
			// event begin time won't yet have beginOffsetSet;
			// fixes PR 56686(version 7 and 8):
			|| pElement->m_pSourceElement->
			m_bHasAtLeastOneNonEventBasedBegin) )
#else
			// Fixes PR 86106(version2): if this excl is in
			// 2nd or subsequent child of seq then any updates to
			// any prior sibling's duration wasn't causing this
			// excl to adjust its children's delays accordingly.
			// Now, we do so if and only if m_bDelaySet and has
			// a non-event-based begin:
			||  pElement->m_bDelaySet  &&
			pElement->m_pSourceElement->
			m_bHasAtLeastOneNonEventBasedBegin 
			) )
#endif
	    {
		pElement->resetDelay(m_pSourceElement->m_ulDelay);
	    }
	    // /else leave delay unresolved.
	}
    }

    // /To fix PR 59851(seq of excls), we need to update our next-in-seq
    // (m_pDependent) as well as make sure sync-arc listeners know we've
    // changed our overall time bounds delay as well;
    if (m_pDependent && m_bDurationSet  &&
	    ulPriorDelay != m_pSourceElement->m_ulDelay)
    {
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	ULONG32 ulTotalDelay = 0;
	if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	}

	if (HXR_OK !=
		m_pSourceElement->getCurrentScheduledStopTime(ulTotalDelay))
	{
	    goto doneSettingDependent;
	}
#else
	ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration;
	if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	{
	    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay);
		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			ulTotalDelay)
		{
		    ulTotalDelay -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }
	}
#endif
	if (WAY_IN_THE_FUTURE < ulTotalDelay)
	{
	    HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
	    ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	}
 
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION) 
{ 
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout? 
	    ADDDURATION_DEBUGOUT_STR_NEW_FILE : 
	    ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE ); 
    ::fprintf(f1, "\n\t%s:CSmilTimelineExcl::resetDelay(%lu):from %lu to %lu;"
	    "\tresetting dependent (%s)'s delay to %lu\n", (const char*)m_pID,
	    ulDelay, ulPriorDelay, m_pSourceElement->m_ulDelay,
	    (const char*)m_pDependent->m_pID, ulTotalDelay);
    ::fclose(f1); 
    bFirstTimeAddDurDebugout = FALSE; 
} 
#endif 

	m_pDependent->resetDelay(ulTotalDelay);
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
#endif

	// /(Added while fixing PR 59851) Let others know our begin time changed:
	m_pParser->m_pTimelineElementManager->notify(m_pID);
    }
}

void 
CSmilTimelineExcl::adjustDuration()
{
    BOOL    bReset = FALSE;
    UINT32  ulDuration = 0;
    BOOL    bDurationSet = FALSE;
    BOOL    bEndsyncIdDurationFound = FALSE; // /For endsync="[Some ID]"
    // /Fixes excl version of PR 50676 (Added during fix for PR 59584):
    ULONG32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

    if (!m_bDurationSet)
    {
	// /NOTE: If this has children who have not yet resolved their begin
	// times (which is why we're in this if(), then other children whose
	// durations have extended due to pausing will have no effect on
	// this parent.  We need to let this parent update its duration
	// accordingly (and its parents' durs as well).
	goto cleanup;
    }

    if(m_pChildren)
    {
	CHXSimpleList::Iterator i = m_pChildren->Begin();
	for(; i != m_pChildren->End(); ++i)
	{
	    CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);

	    // /Checking this fixes excl version of PR 69290: if child duration
	    // isn't set yet, don't use it here:
	    if (!pElement->m_bDurationSet)
	    {
		continue;
	    }
	    HX_ASSERT((UINT32)-1 != pElement->m_pSourceElement->m_ulDuration);


	    // /Make sure we take endsync into account here:
	    if (SMILEventSourceFirst == m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (!bDurationSet)
		{
		    ulDuration = pElement->m_pSourceElement->m_ulDuration;
		}
		else
		{
    		    ulDuration = (ulDuration < pElement->m_pSourceElement->m_ulDuration) ?
			    ulDuration : pElement->m_pSourceElement->m_ulDuration;
		}
		bDurationSet = TRUE;
	    }
	    else if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (pElement->m_pSourceElement->m_pNode  &&
			m_pSourceElement->m_EndsyncEventSourceID ==
			pElement->m_pSourceElement->m_pNode->m_id)
		{
		    ulDuration = pElement->m_pSourceElement->m_ulDuration;
		    bEndsyncIdDurationFound = TRUE;
		    bDurationSet = TRUE;
		}
	    }
	    // /This else-if block fixes problem in PR 62688 repro case where
	    // restarting a child, prior to all children playing, caused excl
	    // to resolve its dur as if it were endsync="last":
	    else if (SMILEventSourceAll ==
		    m_pSourceElement->m_nEndsyncEventSourceTag)
	    {
		if (m_pChildren  &&
			m_nDurationAdded >= m_pChildren->GetCount())
		{
    		    ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
			    ulDuration : pElement->m_pSourceElement->m_ulDuration;
		    bDurationSet = TRUE;
		}
		else
		{
		    // /Don't adjust duration until all child durs are in:
		    goto cleanup;
		}
	    }
	    else // /For "last", use the largest child duration:
	    {
		ulDuration = (ulDuration > pElement->m_pSourceElement->m_ulDuration) ?
			ulDuration : pElement->m_pSourceElement->m_ulDuration;
		bDurationSet = TRUE;
	    }

	    // /Fixes PR 50806 (excl versions 1 & 2): if this has "min"
	    // attribute set, ulDuration shouldn't be less regardless
	    // of endSync:
	    if (m_pSourceElement->m_ulMinActiveDur > ulDuration)
	    {
		ulDuration = m_pSourceElement->m_ulMinActiveDur;
	    }
	}

	// /!bDurationSet happens in PR 50588 (case 2: begin="x.end"), when
	// child has begun playing but has not yet resolved its duration:
	if (!bDurationSet)
	{   HX_ASSERT(bDurationSet  &&  "contact-ehodge");
	    goto cleanup;
	}

	if (SMILEventSourceID == m_pSourceElement->m_nEndsyncEventSourceTag)
	{ 
	    if (!bEndsyncIdDurationFound)
	    {
		goto cleanup; // /That id'd child not added to timeline yet.
	    }
	} 
//check m_ulAuthoredDur here:
	if (!m_pSourceElement->m_bHasExplicitEnd  &&
		!m_pSourceElement->m_bHasExplicitDur)
	{ 
	    m_pSourceElement->m_ulDuration = ulDuration;
	}
    
	// /Moved this out of the above if() so it gets called every time, to
	// fix PR 6XXX? and re-fix PR 55117: we should always give our parents
	// a chance to set the outer-time-container duration so it can (re)-
	// state to the core what the group duration should be:
	if(m_pParent)
	{
	    m_pParent->adjustDuration();
	}

	// /Moved this out to happen all the time, too:
	if (m_pDependent)
	{
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
	    ULONG32 ulTotalDelay = 0;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		  m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(0  &&  "ehodge: CHANGE NOT TESTED!");
	    }

	    if (HXR_OK != m_pSourceElement->getCurrentScheduledStopTime(
		    ulTotalDelay))
	    {
		goto doneSettingDependent;
	    }
#else
	    ULONG32 ulTotalDelay = m_pSourceElement->m_ulDelay +
		    m_pSourceElement->m_ulDuration;
	    if (m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1);
/*OK[]*/		if (m_pSourceElement->m_ulBeginOffsetFromSyncBase != (UINT32)-1)
		{
		    HX_ASSERT(m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay);
		    if (m_pSourceElement->m_ulBeginOffsetFromSyncBase <
			    ulTotalDelay)
		    {
			ulTotalDelay -=
				m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		    }
		}
	    }
#endif
	    if (WAY_IN_THE_FUTURE < ulTotalDelay)
	    {
		// /XXXEH- If delay is greater than this, I want to know:
		HX_ASSERT(WAY_IN_THE_FUTURE == ulTotalDelay  &&  "PR 59584");
		ulTotalDelay = WAY_IN_THE_FUTURE; // /For PR 59584.
	    }

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
{
FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
	ADDDURATION_DEBUGOUT_STR_NEW_FILE :
	ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
::fprintf(f1, "\n\t%s:CSmilTimelineExcl::adjustDuration();\tresetting dependent (%s)'s delay to %lu\n",
	(const char*)m_pID, (const char*)m_pDependent->m_pID, ulTotalDelay);
::fclose(f1);
bFirstTimeAddDurDebugout = FALSE;
}
#endif

	    m_pDependent->resetDelay(ulTotalDelay);
	}
#if defined(XXXEH_WAIT_UNTIL_getCurrentScheduledStopTime_IS_FIXED_WHEN_BEGINOFFSETSET_20011022)
doneSettingDependent:
	;
#endif
    }

    // /Fixes PR 69410 (with outer excl): do this no matter what, even if
    // prior < ulDur; resumed element in excl should extend this excl but
    // we've already told the core to limit the presentation duration,
    // so extend it here as needed:
    // /(Added while fixing PR 59584): if our duration got reduced, we need to
    // possibly constrain our children:
    {
	// /For PR 62688 & PR 59584: remove check for ulPriorDuration being
	// WAY_IN_THE_FUTURE since PR 50676 works without it and there are
	// cases where our dur may re-resolve, & updating children is needed:

	// This group's outer time container, if this is one, needs
	// to set the duration if its dur is longer than its group's so far
	// or if its previous duration was unresolved and now is resolved:
	if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	{
	    if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
		    m_pSourceElement->m_pNode->m_pParent->m_tag  ||
		    m_pSourceElement->m_pNode->
/*OK[]*/		    m_pParent->m_bIsOuterWrapperTimeContainer) )
	    {
		// /The group duration should be the duration of this
		// outer-most time container:
		HX_RESULT pnrs = m_pSourceElement->m_pHandler->
			resolveGroupDurToOuterTimeContainerDur(
			m_pSourceElement->m_pNode->m_nGroup,
			m_pSourceElement->m_ulDuration);
	    }
	}

	if(m_pChildren)
	{
	    // /Accounting for begin offset of this helps fix PR 65741(excl)
	    // where excl w/begin="5s' was including that 5s in dur passed
	    // to children, thus children were playing 5s too long:
	    ULONG32 ulSyncBaseDurationForChildren =
		    m_pSourceElement->m_ulDuration;
	    if (m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase  &&
		    m_pSourceElement->m_bDurationIncludesDelayBeyondSyncbase)
	    {
		HX_ASSERT(ulSyncBaseDurationForChildren >=
			m_pSourceElement->m_ulBeginOffsetFromSyncBase);
		if (ulSyncBaseDurationForChildren >=
			m_pSourceElement->m_ulBeginOffsetFromSyncBase)
		{
		    ulSyncBaseDurationForChildren -=
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase;
		}
	    }

	    CHXSimpleList::Iterator i = m_pChildren->Begin();
	    for(; i != m_pChildren->End(); ++i)
	    {
		CSmilTimelineElement* pElement = (CSmilTimelineElement*)(*i);
		if (pElement->m_pSourceElement  &&
			pElement->m_pSourceElement->m_ulDuration >
			m_pSourceElement->m_ulDuration)
		{
		    pElement->setDuration(ulSyncBaseDurationForChildren, TRUE);
		}
	    }
	}
    }

cleanup:

    m_pParser->m_pTimelineElementManager->notify(m_pID);

    return;
}

void 
CSmilTimelineExcl::addDuration(UINT32 ulDuration,
			      UINT32 ulDelay,
			      UINT32 ulChildDelayBeyondStartOfThis, 
			      const char* pElementID)
{
    BOOL bHandled = FALSE;

    UINT32 ulPriorPureDuration = m_pSourceElement->getPureDuration();

#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
    {
	FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", bFirstTimeAddDurDebugout?
		ADDDURATION_DEBUGOUT_STR_NEW_FILE :
		ADDDURATION_DEBUGOUT_STR_APPEND_TO_FILE );
	::fprintf(f1, "CSmilTimelineExcl{%s}::addDuration(dur=%lu, delay=%lu, "
		"childDelayBeyondThis=%lu, id=%s) m_bDurationSet=%sE\n",
		(const char*)m_pID, ulDuration, ulDelay,
		ulChildDelayBeyondStartOfThis, pElementID,
		m_bDurationSet?"TRU":"FALS");
	::fclose(f1);
	bFirstTimeAddDurDebugout = FALSE;
    }
#endif

    // /If we're inside a seq, our true "sync base" is not the seq but rather
    // the prievious seq sibling (if any).  We need to adjust the ulDelay, if
    // we're in a seq, down to just ulChildDelayBeyondStartOfThis, which is
    // the delay from the prior sibling, not from the seq:
    ULONG32 ulDelayBeyondSyncBase = 0;
    SMILNode* pSyncBaseNode = NULL;
    if (m_pSourceElement->m_pNode)
    {
	pSyncBaseNode = m_pParser->getSyncAncestor(
	    m_pSourceElement->m_pNode);
    }
    if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
    {
	HX_ASSERT(pSyncBaseNode  &&  pSyncBaseNode->m_pElement);
    }
    // /Do this for all time containers (for part of PR52110 post-fix-delay-
    // offset-bug):
    else
    {
	ulDelayBeyondSyncBase = ulChildDelayBeyondStartOfThis;
    }

    BOOL bSetChildCurEndClippedByParent = FALSE;
    BOOL bSetCompletelyRemovedFromTimeline = FALSE;
    BOOL bIsCurChildsFirstAddDuration = FALSE;
    ULONG32 ulCurChildPriorAddedDuration = (UINT32)-1;
    if (!(*m_pChildDurAddedMap)[pElementID])
    {
	bIsCurChildsFirstAddDuration = TRUE;
    }
    else
    {
	ulCurChildPriorAddedDuration =
		(ULONG32)((*m_pChildDurAddedMap)[pElementID]);
    }

    ULONG32 ulActualDurBeyondSyncBase =
	    ulDuration + ulDelayBeyondSyncBase - ulChildDelayBeyondStartOfThis;

// /XXXEH-20020106-test:    HX_ASSERT(WAY_IN_THE_FUTURE >= ulActualDurBeyondSyncBase);

    // /Start of fix for PR 55117: explicit dur or end on par should not be
    // overridden by some punk child's dur; if this has an explicit
    // end or dur, don't do anything to its duration based on children durs:
    // /XXXEH- TODO: determine what wins between endsync VS either end or dur
    // if both are specified; here, I assume end|dur wins over endsync:
    if (m_pSourceElement->m_bHasExplicitDur  ||
	    m_pSourceElement->m_bHasExplicitEnd)
    {
	if ((UINT32)-1 != m_pSourceElement->m_ulDuration  &&
		(!m_bDurationSet  ||
		!m_pSourceElement->m_bAddDurationAlreadyDone) )
	{
	    HX_ASSERT((UINT32)-1 != m_pSourceElement->m_ulDelay);
	    HX_ASSERT(m_pSourceElement->m_ulDuration ==
		    m_pSourceElement->getPureDuration());
	    durationResolved(m_pSourceElement->m_ulDuration, FALSE);
	}
	// /Helps fix PR 6XXXZ (PR 55117 revisited): par in seq where par has explicit dur and
	// children all have smaller durations, we need to give outer time
	// container a chance to hold the presentation open; this is needed
	// when this par is last one in presentation.  (Note: body doesn't set
	// the presentation time during createElements() phase because it
	// doesn't have m_pHandler yet then):
	adjustDuration();
	bHandled = TRUE;
    }
    // /Fixes SMIL 1.0's endsync="id(xyz)" and enables SMIL 2.0's
    // id-based endsync: endsync="xyz":
    else if (m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceID)
    {
	if (!m_pSourceElement->m_EndsyncEventSourceID.IsEmpty()  &&
	        !strcmp(m_pSourceElement->m_EndsyncEventSourceID,pElementID))
	{
	    // /Don't just use ulDuration in case child has a begin offset
	    // or otherwise has a delay beyond this's delay.
	    m_pSourceElement->m_ulDuration = ulActualDurBeyondSyncBase;
	    durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    bHandled = TRUE;
	}
    }
    else if(m_pSourceElement->m_nEndsyncEventSourceTag == SMILEventSourceAll)
    {
	// /Hold excl open until all children have had a chance to begin;
	// leave the excl's duration unresolved awaiting the final child's
	// call to "addDuration" (which may never come if child's begin
	// never resolves):

	// /Helps fix PR 62688(excl version): first, check if all children
	// have resolved already; if so, then duration is set so we can't
	// extend it if begin is after parent excl ended:
	if (m_nDurationAdded >= m_pChildren->GetCount()  &&
		m_pSourceElement->m_ulDuration < ulActualDurBeyondSyncBase)
	{
	    bSetChildCurEndClippedByParent = TRUE;
	    HX_ASSERT(m_ulLastDuration == m_pSourceElement->m_ulDuration);
	    if (m_ulLastDuration > ulChildDelayBeyondStartOfThis)
	    {
		// /Helps fix PR 50660 by removing PR 62688-fix code here that
		// turned out to be unnecessary since code elsewhere completely
		// fixes PR 62688.  Child should be allowed to extend its
		// parent's duration except if it begins *after* its parent has
		// already ended, which is how we got here, so do nothing.
	    }
	    else // /Begin offset is beyond parent's end, so remove it:
	    // helps fix PR 62688(excl) (endsync="all" version of PR 64158)
	    {
		bSetCompletelyRemovedFromTimeline = TRUE;
		HX_RESULT retval2 = m_pSourceElement->m_pHandler->
			handleTrackRemoval((const char*)pElementID,
			(INT32)m_pSourceElement->m_pNode->m_nGroup);
	    }
	}

	if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
		!m_bFirstDurationHasBeenSet)
	{
	    m_ulFirstDuration = ulActualDurBeyondSyncBase;
	    m_bFirstDurationHasBeenSet = TRUE;
	}
	if(ulActualDurBeyondSyncBase > m_ulLastDuration)
	{
	    m_ulLastDuration = ulActualDurBeyondSyncBase;
	}
	// /This helps fix PR 62688(par version): this is used to see if
	// we've already resolved our duration (because all children have
	// weighed in):
	INT32 lTotalDurationsAddedIncludingThisOne = (INT32)m_nDurationAdded;
	if (bIsCurChildsFirstAddDuration)
	{
	    lTotalDurationsAddedIncludingThisOne++;
	}
	if (lTotalDurationsAddedIncludingThisOne < m_pChildren->GetCount()  &&
		// /To help fix PR 59584(excl version), only do this once:
		WAY_IN_THE_FUTURE != m_pSourceElement->m_ulDuration)
	{
	    // /XXXEH- need a better way, but for now let's say it's
	    // resolved to a very big number until all children have
	    // resolved begins:
	    durationResolved(WAY_IN_THE_FUTURE, TRUE);
	}
    }
    else if(m_pSourceElement->m_ulDuration == (UINT32)-1)
    {
	// /Added delay to duration which works in:
	// "BUG-20010430_endHappening2sTooEarlyForExclThatHas"...
	// ..."2.7sBeginAndDurBasedOnChild(totalPresentationDur5.7s).smil":
	m_pSourceElement->m_ulDuration = ulDuration + ulDelayBeyondSyncBase -
		// /Works in excl version of
		// "BUG-20010502(at0700hrs))_firstOu"..."2ndChildIsExcl.smil"
		// /(NOTE: this will be non-zero in the case where the parent
		// excl (this) has endsync="first" and is adding first child
		// due to an event:
		ulChildDelayBeyondStartOfThis;
	m_ulFirstDuration = ulActualDurBeyondSyncBase;
	m_bFirstDurationHasBeenSet = TRUE;
	if (WAY_IN_THE_FUTURE >= m_pSourceElement->m_ulDuration  &&
		!bIsCurChildsFirstAddDuration  &&
		WAY_IN_THE_FUTURE <= ulCurChildPriorAddedDuration)
	{
	    HX_ASSERT(0); // /TESTING! PR 59584.
	    // then don't do the next line (?):
	}
	m_ulLastDuration = ulActualDurBeyondSyncBase;
    }
    else
    // /An excl time container can only have one active track at a time,
    // but it can know that it will play subsequent ones if they have
    // resolved delays (which is how we entered this "else" block, so we
    // need to calculate the excl's duration as the latest that any resolved
    // element will play as far as we know at this point.  Excl's duration
    // in many cases will then vary as childrens' delays become resolved
    // over time:
    // /XXXEH- test this!!!  I left it the same as for Par, but we should
    // consider interrupt behavior of the excl's elements since one may
    // not start while another "uninterruptable" element is playing and
    // thus may not affect the excl's initial dur:
    {
	m_pSourceElement->m_ulDuration = 
	    (ulActualDurBeyondSyncBase > m_pSourceElement->m_ulDuration) ?
	    ulActualDurBeyondSyncBase : m_pSourceElement->m_ulDuration;
	// /XXXEH- TODO: handle m_ulFirst...etc. (or make sure they work) now
	// that delay is being added (as it should be) to m_ulDuration, above:
	if(ulActualDurBeyondSyncBase < m_ulFirstDuration  ||
		!m_bFirstDurationHasBeenSet)
	{
	    m_ulFirstDuration = ulActualDurBeyondSyncBase;
	    m_bFirstDurationHasBeenSet = TRUE;
	}
	if(ulActualDurBeyondSyncBase > m_ulLastDuration)
	{
	    m_ulLastDuration = ulActualDurBeyondSyncBase;
	}
    }

    if (!(*m_pChildDurAddedMap)[pElementID])
    {
	m_nDurationAdded++;
	(*m_pChildDurAddedMap)[pElementID] = (void*)ulActualDurBeyondSyncBase;
    }
    ULONG32 ulChildrenCount = m_pChildren->GetCount();
    // /Fixes PR 56481(excl version) find children that don't have a scheduled
    // begin, i.e., are awaiting an event to begin.  endsync="last" says to
    // ignore any children that never play, and we don't know if those
    // event-based begin children will play or not so ignore them for now,
    // and if they ever do begin, *then* re-compute this excl's duration:
    ULONG32 ulNonEventBasedBeginChildCount = 0;
    CSmilElement* pCurChildElem = NULL;
    CHXSimpleList::Iterator i = m_pChildren->Begin();
    for(i; i != m_pChildren->End(); ++i)
    {
	CSmilTimelineElement* pTmlnElement =
		(CSmilTimelineElement*)(*i);
	if (pTmlnElement  &&  pTmlnElement->m_pSourceElement)
	{
	    BOOL isCurAddDurElem = FALSE;
	    if (!strcmp(pTmlnElement->m_pSourceElement->m_pNode->m_id,
		    pElementID))
	    {
		isCurAddDurElem = TRUE;
		pCurChildElem = pTmlnElement->m_pSourceElement;
		if (bSetChildCurEndClippedByParent  &&  pCurChildElem)
		{
		    pCurChildElem->m_bCurEndClippedByParent = TRUE;
		}
		if (bSetCompletelyRemovedFromTimeline  &&  pCurChildElem)
		{
		    pCurChildElem->m_bInsertedIntoTimeline = FALSE;
		}
	    }
	    if ((pTmlnElement->m_pSourceElement->
		    m_bHasAtLeastOneNonEventBasedBegin  ||
		    // /Do this so this par can re-resolve its duration if &
		    // when an event-based-begin child gets added (and thus
		    // technically now is a child with a clock-valued begin):
		    isCurAddDurElem) )
	    {
		ulNonEventBasedBeginChildCount++;
	    }
	}
    }
    
    if (!bHandled  &&
	    (m_nDurationAdded >= ulNonEventBasedBeginChildCount  &&
	    // /If endsync is all, we need to wait for *all* to be added:
	    (SMILEventSourceAll!=m_pSourceElement->m_nEndsyncEventSourceTag  ||
	    m_nDurationAdded == ulChildrenCount) )  &&
	    !m_bDurationEvent)
    {
	BOOL bUpdateDurMightBeNeeded = FALSE;
	// /Helps fix PR 62688(excl): if duration was set before, but only to
	// hold the timeline open until all (or a particular) child duration
	// became known, then we want to ignore the durationSet flag so that
	// we call duartionResolved() instead of adjustDuration();
	BOOL bIgnoreDurationSetFlag = bIsCurChildsFirstAddDuration  &&
		(WAY_IN_THE_FUTURE <= m_pSourceElement->m_ulDelay +
		m_pSourceElement->m_ulDuration);
	// /First, if duration has already been set, then pElement must be an
	// event-based-begin child that just resolved, so we need to reset
	// our duration appropriately:
	if (m_bDurationSet  &&  pCurChildElem  &&  !bIgnoreDurationSetFlag  &&
		!pCurChildElem->m_bHasAtLeastOneNonEventBasedBegin)
	{
	    bUpdateDurMightBeNeeded = TRUE;
	}

	if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceFirst)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulFirstDuration)
		{
		    // /XXXEH- revisit now that addDuration accts for endsync:
		    ULONG32 ulOldDur = m_pSourceElement->m_ulDuration;
		    adjustDuration();
		    HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulFirstDuration);
		    // /Other half of fix for PR 50679: if updated duration
		    // is less than prior dur, then update timeline element:
		    if (ulOldDur > m_pSourceElement->m_ulDuration)
		    {
			// /Reset duration-set flag to FALSE since we want to
			// override (reset) the dur now that this last child
			// has been resolved (presumably after playback of
			// this par began):
			m_bDurationSet = FALSE;
			durationResolved(m_pSourceElement->m_ulDuration, TRUE);
		    }
		}
	    }
	    else
	    {
		durationResolved(m_ulFirstDuration, TRUE);
	    }
	}
	else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceLast)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulLastDuration)
		{
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 59584(simplified): if we previously resolved
		// our duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			// /See "part 2 of PR 79699" above; don't want to mess
			// with this unless there's content that asserts here:
			HX_ASSERT(m_bDurationSet);
		    }
		    adjustDuration();
		    m_bDurationSet = FALSE;
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		// /To fix PR 59584(exclVersionSimplified, w/"last"), use
		// m_pSourceE.'s dur, not m_ulLastDuration since latter may
		// be wrong if some elements stopped early
		durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    }
	}
	else if(m_pSourceElement->m_nEndsyncEventSourceTag == 
	    SMILEventSourceAll)
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_ulLastDuration)
		{
		    // /adjustDuration() assumes endsync=last which is OK
		    // since we've got all durations:
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 59584(excl, simpl.): if we previously resolved
		// our duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			// /See "part 2 of PR 79699" above; don't want to mess
			// with this unless there's content that asserts here:
			HX_ASSERT(m_bDurationSet);
		    }
		    adjustDuration();
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration ==
			m_pSourceElement->getPureDuration());
		// /Reset duration-set flag to FALSE since we want to
		// override (reset) the dur now that this last child has been
		// resolved (presumably after playback of this par began):
		m_bDurationSet = FALSE;
		// /To fix PR 59584(exclVersionSimplified), use m_pSourceE.'s
		// duration, not m_ulLastDuration since latter may be wrong
		// if some elements stopped early:
		durationResolved(m_pSourceElement->m_ulDuration, TRUE);
	    }
	}
	else
	{
	    if (bUpdateDurMightBeNeeded)
	    {
		if (ulActualDurBeyondSyncBase == m_pSourceElement->m_ulDuration)
		{
		    adjustDuration();
		}
	    }
	    else
	    {
		// /Helps fix PR 62688(excl version): if we previously resolved
		// our duration to "unresolved" to hold timeline open, then we
		// need to adjust our duration down from WAY_IN_THE_FUTURE:
		if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  ||
			WAY_IN_THE_FUTURE == m_ulLastDuration  ||
			m_pSourceElement->m_ulDuration != m_ulLastDuration)
		{
		    if (WAY_IN_THE_FUTURE == m_pSourceElement->m_ulDuration  &&
			    bIsCurChildsFirstAddDuration)
		    {
			// /See "part 2 of PR 79699" above; don't want to mess
			// with this unless there's content that asserts here:
			HX_ASSERT(m_bDurationSet);
		    }
		    adjustDuration();
		    m_bDurationSet = FALSE;
		}
		HX_ASSERT(m_pSourceElement->m_ulDuration == m_ulLastDuration);
		durationResolved(m_pSourceElement->m_ulDuration, FALSE);
	    }
	}
	// /This if() block fixes PR 56686 (version 4) and
	// PR 61174 (version 4): if time container has longer dur than its
	// children and it is not a time-child of the <body>, then its dur
	// was never getting accounted for, but now the outer time container
	// sets the duration if its dur is longer than its group's so far;
	// outer time contnr can only be a par if body has multiple children:
	if (m_pSourceElement->m_pNode  &&  m_pSourceElement->m_pHandler)
	{
	    // /XXXEH- handle <body><switch><par> and <body><a><par>
	    if (m_pSourceElement->m_pNode->m_pParent  &&  (SMILBody == 
		    m_pSourceElement->m_pNode->m_pParent->m_tag  ||
		    m_pSourceElement->m_pNode->
/*OK[]*/		    m_pParent->m_bIsOuterWrapperTimeContainer) )
	    {
		UINT32 ulGroup = m_pSourceElement->m_pNode->m_nGroup;
		// /The group duration should be the duration of this
		// outer-most time container:
		HX_RESULT pnrs = m_pSourceElement->m_pHandler->
			resolveGroupDurToOuterTimeContainerDur(
			ulGroup, m_pSourceElement->m_ulDuration);
	    }
	}
    }
}

void
CSmilTimelineExcl::elementResolved(CSmilTimelineElement* pEventElement)
{
    parExclElementResolved(pEventElement);
}

void
CSmilTimelineExcl::durationResolved(UINT32 ulDuration, BOOL bUpdateChildren)
{
    parExclDurationResolved(ulDuration, bUpdateChildren);
}

/***************************************************************************/

/*
 * CSmilTimelineAnchor methods
 */

CSmilTimelineAnchor::CSmilTimelineAnchor(CSmilElement* pSourceElement,
				   CSmilParser* pParser):
    CSmilTimelineElement(pSourceElement, pParser)
    , m_nDurationAdded(0)
{
}

CSmilTimelineAnchor::~CSmilTimelineAnchor()
{
}

void
CSmilTimelineAnchor::elementResolved(CSmilTimelineElement* pEventElement)
{
    //First, let's see if we have a begin event to resolve:
    if ( (m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    //[SMIL 1.0 Compliance] Helps fix 14420:
	    if (m_bNonEventDelaySet)
	    {
		//Add non-event delay to syncArc element's delay + clock offset:
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
	    }
	    else
	    {
		m_ulNonEventDelay = 0;
		//Just set delay to syncArc element's delay:
		//Do the following in case sum is negative; if so, we
		// want to use zero.
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			// /Fixes case where anchor/area has begin="foo.begin+5s"
			// we need to account for the 5s here:
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = (ULONG32)lSum;

		// /Now, we need to set the vars that keep track of our
		// offset from our syncBase element because isCurrentLink
		// uses times relative to our syncBase:
		SMILNode* pSyncNode = (!m_pParser? NULL :
		       m_pParser->getSyncAncestor(m_pSourceElement->m_pNode));
		HX_ASSERT(pSyncNode  &&  pSyncNode->m_pElement);
		if (pSyncNode  &&  pSyncNode->m_pElement)
		{ 
		    ULONG32 ulSyncBaseDelay =
			    pSyncNode->m_pElement->m_ulDelay;
		    HX_ASSERT((UINT32)-1 != ulSyncBaseDelay);
		    if ((UINT32)-1 != ulSyncBaseDelay  &&
			    (UINT32)-1 != m_pSourceElement->m_ulDelay )
		    { 
			HX_ASSERT(m_pSourceElement->m_ulDelay >=
				ulSyncBaseDelay);
			m_pSourceElement->m_bCurBeginIsOffsetFromSyncBase =
				TRUE;
			if (m_pSourceElement->m_ulDelay >= ulSyncBaseDelay)
			{ 
			    ULONG32 ulEffectiveBeginOffset =
				    m_pSourceElement->m_ulDelay -
				    ulSyncBaseDelay;
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase =
				    ulEffectiveBeginOffset;
			} 
			else
			{ 
			    m_pSourceElement->m_ulBeginOffsetFromSyncBase = 0;
			} 
		    } 
		} 
	    }

	    m_bNonEventDelaySet = m_bDelaySet = TRUE;
	    if(m_pChildren)
	    {
		CHXSimpleList::Iterator i = m_pChildren->Begin();
		for(; i != m_pChildren->End(); ++i)
		{
		    CSmilTimelineElement* pElement =
			    (CSmilTimelineElement*)(*i);
		    pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		}
	    }
	}
    }
    else if(m_pSourceElement->m_nBeginEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_BeginEventSourceID == pEventElement->m_pID)
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration)
	{
	    //[SMIL 1.0 Compliance] Helps fix 14420:
	    if (m_bNonEventDelaySet)
	    {
		//Add non-event delay to syncArc element's delay + clock offset:
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDuration +
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			// /Fixes begin="foo.end+5s"; 5s was being ignored:
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_pSourceElement->m_ulDelay = m_ulNonEventDelay + (ULONG32)lSum;
	    }
	    else
	    {
		//Add non-event delay to syncArc element's delay + clock offset:
		LONG32 lSum =
			(LONG32)pEventElement->m_pSourceElement->m_ulDuration +
			(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
			// /Fixes PR 68495 begin="foo.end+5s"; 5s was ignored
			// without the following:
			m_pSourceElement->m_lBeginEventClockValue;
		HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
		lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
		m_ulNonEventDelay = 0;
		m_pSourceElement->m_ulDelay = (ULONG32)lSum;
	    }
	    m_bNonEventDelaySet = m_bDelaySet = TRUE;
	    if(m_pChildren)
	    {
		CHXSimpleList::Iterator i = m_pChildren->Begin();
		for(; i != m_pChildren->End(); ++i)
		{
		    CSmilTimelineElement* pElement =
			    (CSmilTimelineElement*)(*i);
		    pElement->setDelay(m_pSourceElement->m_ulDelay, TRUE);
		}
	    }
	}
    }

    
    //XXXEH-The following cases need to be tested!:
    if ( (m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceBegin  ||
	    m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceClock)  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	if(pEventElement->m_bDelaySet)
	{
	    LONG32 lSum =(LONG32)pEventElement->m_pSourceElement->m_ulDelay +
    		    m_pSourceElement->m_lEndEventClockValue;
	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
	    durationResolved((ULONG32)lSum);
	}
    }
    else if(m_pSourceElement->m_nEndEventSourceTag == SMILEventSourceEnd  &&
	    m_pSourceElement->m_EndEventSourceID == pEventElement->m_pID)
    {
	// /If event element's duration is "WAY_IN_THE_FUTURE" then it's
	// essentially an unresolved end time, so we should not resolve
	// based on it:
	if(pEventElement->m_bDurationSet  &&  WAY_IN_THE_FUTURE !=
		pEventElement->m_pSourceElement->m_ulDuration)
	{
	    LONG32 lSum =(LONG32)pEventElement->getDuration() +
		    m_pSourceElement->m_lEndEventClockValue;
	    // /If the event element has a delay, we need to add that:
	    if(pEventElement->m_bDelaySet)
	    {
		lSum += (LONG32)pEventElement->m_pSourceElement->m_ulDelay;
		if (pEventElement->m_pSourceElement->m_bBeginOffsetSet)
		{
		    lSum -= pEventElement->m_pSourceElement->m_lBeginOffset;
		}
	    }
	    HX_ASSERT(lSum >= 0  &&  "ehodge: handle neg delay propogation");
	    lSum = (lSum<0? 0 : lSum);  //clip off negative vals.
	    durationResolved((ULONG32)lSum);
	}
    }
}

void
CSmilTimelineAnchor::durationResolved(UINT32 ulDuration)
{
    if(!m_bDurationSet)
    {
	m_bDurationSet = TRUE;
	m_pSourceElement->m_ulDuration = ulDuration;
    }
}


CSmilTimelineAnimate::CSmilTimelineAnimate(CSmilElement* pSourceElement,
                                           CSmilParser* pParser)
    : CSmilTimelineElement(pSourceElement, pParser)
{
}

CSmilTimelineAnimate::~CSmilTimelineAnimate()
{
}

void CSmilTimelineAnimate::setDuration(UINT32 ulDuration, BOOL bSetFromParent,
				  BOOL bDurationExtendingDueToPause)
{
    if (!bSetFromParent)
    {
        CSmilTimelineElement::setDuration(ulDuration, bSetFromParent,
				  bDurationExtendingDueToPause);
    }
}

