⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smlparse.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    m_bFirstPacket = TRUE;

    // Clear the begin time map
    clearTimeValueMap(SmilBeginTimeList);
    // Clear the end time map
    clearTimeValueMap(SmilEndTimeList);
    // Clear and delete the custom event list
    clearExternalEventList();
    HX_DELETE(m_pExternalEventList);
    // Clear the handler list
    HX_DELETE(m_pElementsWithHandlerList);
}

HX_RESULT
CSmilParser::init(BOOL bStoreErrors)
{
    HX_RESULT rc = HXR_OK;

    close();
    m_pNodeListStack = new CHXStack;
    m_pPacketQueue = new CHXSimpleList;
    m_pIDMap = new CHXMapStringToOb;
    m_pAddGroupMap = new CHXMapLongToObj;
    m_bStoreErrors = bStoreErrors;
    if (m_bStoreErrors)
    {
	// XXXJHUG  error stuff.
	// In the future if there was any reason, we could
	// store the errors in the nodes that the errors occurred in.
	// for now when we get an error notification, we will
	// just call the storeError function which will add
	// a new IHXBuffer to this array..  This will also be
	// called when problems are found with tags...
	// this will save having to walk the tree when it
	// is time to dump the errors.
	m_pErrors = new CHXPtrArray;
    }

    SMILNode* pRootNode = new SMILNode;
    pRootNode->m_id = "root";
    pRootNode->m_name = "root";
    m_pNodeList = new SMILNodeList;
    pRootNode->m_pNodeList = m_pNodeList;
    m_pNodeList->m_pParentNode = pRootNode;
    m_pNodeListStack->Push(pRootNode);
#if !defined(USE_EXPAT_FOR_SMIL)
//#define USE_EXPAT_FOR_SMIL
#endif
#ifdef USE_EXPAT_FOR_SMIL
    rc = m_pClassFactory->CreateInstance(CLSID_IHXXMLParser, (void**)&m_pParser);
    if (FAILED(rc))
    {
	// they don't have the parser...  use old one?
	// Don't QI core for IID_IHXXMLParser; use our own instance.
	m_pParser = new HXXMLParser;
	if (m_pParser)
	{
	    rc = HXR_OK;
	    m_pParser->AddRef();
	}
	else
	{
	    rc = HXR_OUTOFMEMORY;
	}
    }
    if (SUCCEEDED(rc))
    {
	m_pResponse = new CSmilParserResponse(this);
	m_pResponse->AddRef();
	// Expat is created off the CCF.
	// In strict mode it requires 100% compliant XML.
	rc = m_pParser->Init(m_pResponse, "iso-8859-1", TRUE);
    }

#else
    // Don't QI core for IID_IHXXMLParser; use our own instance.
    HXXMLParser* parser = new HXXMLParser();

    if (parser)
    {
	parser->AddRef();
    }
    else
    {
	rc = HXR_OUTOFMEMORY;
    }

    if (SUCCEEDED(rc))
    {
	m_pResponse = new CSmilParserResponse(this);
	m_pResponse->AddRef();
	rc = parser->Init(m_pResponse, NULL, TRUE);	// strict parser
    }
    if (m_bStoreErrors && parser)
    {
	parser->InitErrorNotifier(m_pResponse);
    }
    m_pParser = (IHXXMLParser*)parser;


#endif

    return rc;
}

HX_RESULT
CSmilParser::parse(IHXBuffer* pBuffer, BOOL bIsFinal)
{
    HX_RESULT rc = HXR_OK;

    if (m_bFirstPacket)
    {
	m_bFirstPacket = FALSE;
	time(&m_tRefTime);
    }


    rc = m_pParser->Parse(pBuffer, bIsFinal);
    if (SUCCEEDED(rc) && FAILED(m_lParseError))
    {
        rc = m_lParseError;
    }
    if(HXR_OK != rc)
    {
	m_pParser->GetCurrentLineNumber(m_ulErrorLineNumber);
	m_pParser->GetCurrentColumnNumber(m_ulErrorColumnNumber);
	HX_RELEASE(m_pErrorText);
	m_pParser->GetCurrentErrorText(m_pErrorText);
    }
    return rc;
}



HX_RESULT
CSmilParser::durationResolved(const char* pID, UINT32 ulDuration,
			      // /Defaults to FALSE:
			      BOOL bSetByParent,
			      BOOL bDurationExtendingDueToPause)
{
    HX_RESULT rc = HXR_OK;

    SMILNode*	pNode = NULL;

    if(m_pIDMap->Lookup(pID, (void*&)pNode))
    {
	if (pNode->m_pElement->m_bIndefiniteDuration)
	{
#if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)
	    goto cleanup;
#endif
	}

	// add duration to parent element
	if(pNode &&
	   pNode->m_pElement &&
	   pNode->m_pElement->m_pTimelineElement)
	{
	    pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration,
		    bSetByParent, bDurationExtendingDueToPause);
	}
    }

#if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)
cleanup:
#endif

    return rc;
}

BOOL AncestorEventsAreResolved(SMILNode* pNode, SMILNode* pOriginalChildNode)
{
    if (!pNode  ||  !pNode->m_pElement  ||
	    !pNode->m_pParent  ||  pNode->m_tag == SMILBody)
    {
	return TRUE;
    }
    // /For any parent that's not a timeline element, e.g., priorityClass,
    // just ignore and return its parent's results:
    else if (!pNode->m_pElement->m_pTimelineElement)
    {
	return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode);
    }
    //Now, look to see if its duration and delay events, if any, are
    // resolved:
    if ( ( (pNode->m_pElement->m_pTimelineElement->durationEvent()  &&
	!pNode->m_pElement->m_pTimelineElement->durationSet()  &&
	// /Fixes 1/2 of PR 50535: don't care about duration event for child
	// itself; it's OK to add a timeline element that has an unresolved
	// end; (but if parent has unresolved end, we may need to wait):
	pNode != pOriginalChildNode)  ||
	(pNode->m_pElement->m_pTimelineElement->delayEvent()  &&
	!pNode->m_pElement->m_pTimelineElement->initialDelaySet()) )  &&
	//[SMIL 1.0 compliance] Helps fix PR 32578:
	//However, if we have a duration event and it's based on a child's
	// timing (as can happen via endsync="id(child)", then we want to
	// avoid this element waiting for its parent to be resolved while
	// the parent is waiting for this element to be resolved:
	(!pNode->m_pElement->m_pTimelineElement->durationEvent()  ||
	SMILEventSourceID != pNode->m_pElement->m_nEndsyncEventSourceTag) )
    {
	return FALSE; //We still need to await event resolution.
    }
    //pNode is ok but its dependency ancestors may still be unresolved and
    // thus pNode may still have timing constraints from its dependency
    // ancestors due to their unresolved event(s):
    return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode);
}


HX_RESULT
CSmilParser::adjustForNegativeOffset(const char* pID)
{
    HX_RESULT pnresult = HXR_OK;
    SMILNode* pNode = 0;
    if(!m_pIDMap->Lookup(pID, (void*&)pNode))
    {
	pnresult = HXR_FAILED;
    }
    else if (pNode  &&  pNode->m_pElement  &&
	    !pNode->m_pElement->m_bInsertedIntoTimeline  &&
	    pNode->m_pParent  &&  pNode->m_pParent->m_pElement)
    {
	// /Use syncBase, not parent here (in case parent is <a>, <switch>,
	// or <priorityClass> element); this fixes bug (PR 56233 repro case)
	// where clipBegin was calculted wrong, below, because priorityClass
	// was being used as syncbase and it had a begin time later than this:
	SMILNode* pSyncBaseNode = getSyncAncestor(pNode);
	if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
	{
	    pnresult = HXR_FAILED;
	    goto cleanup;
	}

	// /If we have a negative begin offset or delay which starts us
	// earlier than the begin offset or delay of our syncbase, we need
	// to do a clip-begin equal to the difference, and we need to
	// update our duration as well:
	LONG32 lParentBegin =
		// /If delay is valid, use it otherwise use valid beginOffset
		pSyncBaseNode->m_pElement->m_ulDelay != ((UINT32)-1) ?
		(LONG32)pSyncBaseNode->m_pElement->m_ulDelay :
		pSyncBaseNode->m_pElement->m_bBeginOffsetSet?
		pSyncBaseNode->m_pElement->m_lBeginOffset : 0;
	LONG32 lCurElementBegin =
		pNode->m_pElement->m_ulDelay != ((UINT32)-1) ?
		(LONG32)pNode->m_pElement->m_ulDelay :
		pNode->m_pElement->m_bBeginOffsetSet?
		pNode->m_pElement->m_lBeginOffset :
		// /In adjustForNegativeOffset():
		// /Fixes case where parent has explicit dur, explicit
		// begin offset, and pNode's element begins on an event;
		// this used to set lCurElementBegin to 0 and erroneous
		// clip-begin equal to parent's begin offset would ensue:
		MAX_LONG32;

	// /First, we need to see if this is happening during playback; if
	// so, our begin may have resolved to a time in the past that is
	// later than our sync-parent's begin; in that case, we need to
	// adjust the clip-begin and delay to account for the diff between
	// now and lCurElementBegin:
	if (m_lLastCheckPendingTime > (lCurElementBegin +
		// /(re)Fixes broken long-sync-arc test file
		// BUG-20001110_BeginOffsetInPar...BeginningOnClickAllowsSync.smi
		// where the clipBegin was being *re*-computed here, after
		// having already been adjusted in setDelay() for a long-sync-
		// arc negative offset.  We shouldn't do any adjustment here
		// if the difference is very small (which is not due to
		// user or authored delay clipping, but is due to processor
		// time between when our parent resolved and when the last
		// check pending time):
		CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR))
	{
	    lParentBegin = m_lLastCheckPendingTime;
	}

	if (lCurElementBegin < lParentBegin)
	{
	    LONG32 lDiff = lParentBegin - lCurElementBegin;
	    HX_ASSERT(lDiff >= 0);
	    if (lDiff > 0)
	    {
		ULONG32 ulPriorPureDuration = pNode->m_pElement->getPureDuration();
		ULONG32 ulDiff = (ULONG32)lDiff;
		// /If clip-begin is invalid, set it otherwise add to it:
		pNode->m_pElement->m_ulClipBegin = ((UINT32)-1 ==
			pNode->m_pElement->m_ulAuthoredClipBegin? ulDiff :
			ulDiff+pNode->m_pElement->m_ulAuthoredClipBegin);

		if ((UINT32)-1 != pNode->m_pElement->m_ulDuration)
		{
		    if (pNode->m_pElement->m_ulDuration > ulDiff)
		    {
			pNode->m_pElement->m_ulDuration -= ulDiff;
		    }
		    // /else duration is negative; it can't ever play:
		    else
		    {
			pNode->m_pElement->m_ulDuration = 0;
		    }
		}

		// /And, we should now begin when our parent does:
		pNode->m_pElement->m_ulDelay = lParentBegin;
		// /Only reset duration if it's not 0xFFFFFFFF and
		// if it's not the same as it was before:
		if ((UINT32)-1 != pNode->m_pElement->m_ulDuration  &&
			ulPriorPureDuration != pNode->m_pElement->getPureDuration())
		{
		    resetTimelineElementDuration(pID,
			    pNode->m_pElement->getPureDuration(),
			    ulPriorPureDuration);
		}
                if (m_pTimelineElementManager) m_pTimelineElementManager->notify(pID);
	    }
	}
    }

cleanup:
    return pnresult;
}


void
CSmilParser::insertTimelineElement(const char* pID, UINT32 ulDelay)
{
#if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_ADDDURATION)
{
    FILE* f1 = ::fopen("c:\\smil2AddDuration.txt", "a+");
    ::fprintf(f1, "CSmilParser::insertTimelineElement(%s, delay=%lu) _-_-_-_-_-_-_-_-_\n",
	    (const char*)pID, ulDelay);
    ::fclose(f1);
}
#endif

    SMILNode* pNode = 0;
    if(m_pIDMap->Lookup(pID, (void*&)pNode))
    {
	if(pNode &&
	    pNode->m_pElement &&
	    // /XXXEH- TODO: we need to handle restart!="never" which
	    // means that the following if condition should take this
	    // into account:
	    !pNode->m_pElement->m_bInsertedIntoTimeline  &&
	    //[SMIL 1.0 compliance] Helps fix PR 16629:
	    // We don't want to insert a node into the timeline if
	    // its begin is dependent on another (not-yet-
	    // resolved) element:
	    ((!pNode->m_pElement->m_pTimelineElement->delayEvent()  ||
	    pNode->m_pElement->m_pTimelineElement->initialDelaySet()) )
	    //[SMIL 1.0 compliance] Helps fix 14420:
	    // First, we need to look all the way up the tree of ancestors
	    // to see if any of them have event-based delays or durations
	    // and to make sure the appropriate time(s) are resolved.  If
	    // not, we'll have to await those event resolutions before
	    // inserting this element into the timeline:
	    &&  AncestorEventsAreResolved(pNode, pNode)
	    // /For SMIL 2.0, we can have begin="indefinite" which should
	    // be treated as un unresolved event (but only if that's the
	    // sole begin time specified; begin="indefinite; 5s" should be
	    // treated as begin="5s"):
	    &&  !pNode->m_pElement->m_bIndefiniteBegin
	    )
	{
	    ULONG32 ulDelayBeyondParentDelay = 0;
	    ULONG32 ulSyncBaseDelay = 0;
	    SMILNode* pSyncAncestor = getSyncAncestor(pNode);
	    HX_ASSERT((UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay);

	    // /Check hard time boundaries set by parent:
	    if  (pSyncAncestor  && pSyncAncestor->m_pElement  &&
		    (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
	    {
		ulSyncBaseDelay = pSyncAncestor->m_pElement->m_ulDelay;
		ulDelayBeyondParentDelay = ulDelay - ulSyncBaseDelay;
		HX_ASSERT(ulDelay >= ulSyncBaseDelay);
		if (ulDelay < ulSyncBaseDelay)
		{
		    ulDelayBeyondParentDelay = 0;
		}
		// /If child has delay beyond parent's delay+duration, i.e.,
		// begin resolved on an event or sync arc, then don't insert it:
		else
		{
		    if (pSyncAncestor->m_pElement->m_bHasExplicitDur  &&
			    !pSyncAncestor->m_pElement->m_bIndefiniteDuration  &&
			    !pSyncAncestor->m_pElement->m_bIndefiniteEnd  &&
			    (ulDelayBeyondParentDelay >=
			    pSyncAncestor->m_pElement->m_ulDuration) )
		    {
			goto cleanup; //It can't ever play.
		    }
		    else if (pSyncAncestor->m_pElement->m_bEndOffsetSet  &&
			    !pSyncAncestor->m_pElement->m_bIndefiniteDuration  &&
			    !pSyncAncestor->m_pElement->m_bIndefiniteEnd)
		    {
			if (ulDelayBeyondParentDelay >=
				pSyncAncestor->m_pElement->m_ulDuration)
			{
			    goto cleanup; //It can't ever play.
			}
		    }
		}
	    }
	    else
	    {
		// /Fixes PR 50411: long sync-arc begin resolved before parent
		// begin resolved and is thus not adjusted for any offset
		// from parent begin; dur:=0 if it ends before parent begin:
		if (pSyncAncestor)
		{
		    pNode->m_pElement->m_bAwaitingSyncAncestorBeginNotification=
			    TRUE;
		}
		goto cleanup; // /Wait to insert this until parent is resolved.
	    }

#define XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530
#if defined(XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530)
	    // /[SMIL 1.0 Compliance] Fixes PR 27644:
	    // if our begin offset is same or greater than our parent's
	    // end offset, then we should be ignored:
	    if ( pNode->m_pParent  &&  pNode->m_pParent->m_pElement  &&
		    pNode->m_pElement->m_bBeginOffsetSet &&
		    pNode->m_pParent->m_pElement->m_bEndOffsetSet &&
		    (pNode->m_pElement->m_lBeginOffset >
		    pNode->m_pParent->m_pElement->m_lEndOffset) )
	    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -