smltime.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,795 行 · 第 1/5 页

CPP
1,795
字号
/* ***** 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)
    {

⌨️ 快捷键说明

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