📄 smlelem.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 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
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (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.
*
* 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 "ihxpckts.h"
#include "hxxml.h"
#include "smiltype.h"
// pncont
#include "hxstring.h"
#include "hxslist.h"
#include "hxstack.h"
#include "chxpckts.h"
// pnmisc
#include "nptime.h"
#include "smpte.h"
#include "hxwinver.h"
#include "hxstrutl.h" /* for new_string(). */
// rnxmllib
#include "hxxmlprs.h"
// rmasmil
#include "smlparse.h"
#include "smltime.h"
#include "smlprstime.h"
#include "animattr.h"
#include "smlelem.h"
// pndebug
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
/*
* CSmilElement methods
*/
CSmilElement::CSmilElement(SMILNode* pNode):
m_pNode(pNode),
m_lBeginOffset(0),
m_bBeginOffsetSet(FALSE),
m_bNegBeginOffsetAlreadyUsed(FALSE),
m_bCurBeginIsOffsetFromSyncBase(FALSE),
m_ulBeginOffsetFromSyncBase((UINT32)-1),
m_ulClipBegin((UINT32)-1),
m_ulAuthoredClipBegin((UINT32)-1),
m_ulClipEnd((UINT32)-1),
m_ulDelay((UINT32)-1),
m_ulDuration((UINT32)-1),
m_ulOriginalDuration((UINT32)-1),
m_ulDurationInAddTrack((UINT32)-1),
m_bCurEndClippedByParent(FALSE),
m_ulMaxDuration((UINT32)-1),
m_ulMaxActiveDur((UINT32)-1),
m_ulMinActiveDur(0),
m_ulAuthoredDur((UINT32)-1),
m_bHasExplicitDur(FALSE),
m_bHasExplicitEnd(FALSE),
m_bDurationIncludesDelayBeyondSyncbase(FALSE),
m_bAddDurationAlreadyDone(FALSE),
m_bUseMediaDurForMinDur(FALSE),
m_bUseMediaDurForMaxDur(FALSE),
m_lEndOffset(0),
m_bEndOffsetSet(FALSE),
m_ulAnticipatedPauseDur(0),
m_ulEndSync((UINT32)-1),
m_fRepeatValue(1.0),
m_ulTimestamp(0),
m_bInsertedIntoTimeline(FALSE),
m_bHasBeenScheduled(FALSE),
m_bIsPausedInExcl(FALSE),
m_bIsDeferredInExcl(FALSE),
m_ulTimeDeferralOccurred((UINT32)-1),
m_bIsStoppedInExcl(FALSE),
m_ulStopTimeInExcl((UINT32)-1),
m_bCurrentSourceIsLive(FALSE),
m_bRendererInitialized(FALSE),
m_bIsRestarting(FALSE),
m_bAwaitingSyncAncestorBeginNotification(FALSE),
m_ulLongSyncArcBeginInGroupTime((UINT32)-1),
m_bIndefiniteDuration(FALSE),
m_bIndefiniteEnd(FALSE),
m_bIndefiniteBegin(FALSE),
m_restartBehavior(SmilRestartAlways),
m_restartDefaultBehavior(SmilRestartInherit),
// /Defaults to "default" which means use val of syncToleranceDefault:
m_ulSyncTolerance((UINT32)-1),
// /Defaults to "inherit"; if there is no parent timed element, then
// it is implementation-dependent (but should be less than or = 2s):
m_ulSyncToleranceDefault((UINT32)-1),
m_syncBehavior(SmilSyncBehaviorDefault),
m_syncBehaviorDefault(SmilSyncBehaviorInherit),
m_ulReadIndex(0),
m_nBeginEventSourceTag(SMILEventSourceNone),
m_nEndEventSourceTag(SMILEventSourceNone),
m_nEndsyncEventSourceTag(SMILEventSourceNone),
m_lBeginEventClockValue(0),
m_lEndEventClockValue(0),
m_pHandler(0),
m_pTimelineElement(NULL),
m_pBeginTimeList(NULL),
m_pEndTimeList(NULL),
m_bWallClockBegin(FALSE),
m_bWallClockEnd(FALSE),
m_bHasAtLeastOneEventBasedBegin(FALSE),
m_bHasAtLeastOneNonEventBasedBegin(FALSE),
m_eFill(FillDefault),
m_eFillDefault(FillDefaultInherit),
m_eActualFill(FillDefault),
m_eErase(EraseWhenDone),
m_ulRemoveTime(((UINT32) -1)),
m_bUsesExternalMediaMarkerFile(FALSE),
m_bClipBeginUsesMarker(FALSE),
m_bClipBeginMarkerResolved(FALSE),
m_bWaitingOnClipBeginToResolve(FALSE),
m_pszClipBeginMarkerName(NULL),
m_pszClipBeginExternalMarkerFileName(NULL),
m_bClipEndUsesMarker(FALSE),
m_bClipEndMarkerResolved(FALSE),
m_bWaitingOnClipEndToResolve(FALSE),
m_pszClipEndMarkerName(NULL),
m_pszClipEndExternalMarkerFileName(NULL),
m_eAccessErrorBehavior(AccessErrorBehaviorInherit)
{
// /XXXEH- we may need to set m_bIndefiniteBegin to TRUE if
// hasAncestor(SMILExcl, this), but setInitialDelay() fix seems to be
// all we need (...<==famous last words).
m_pHyperlinks = new CHXSimpleList;
getParentRestartDefault();
}
CSmilElement::~CSmilElement()
{
if (m_pBeginTimeList)
{
CHXSimpleList::Iterator ndx = m_pBeginTimeList->Begin();
for (; ndx != m_pBeginTimeList->End(); ++ndx)
{
SmilTimeValue* pTV = (SmilTimeValue*)(*ndx);
HX_DELETE(pTV);
}
HX_DELETE(m_pBeginTimeList);
}
if (m_pEndTimeList)
{
CHXSimpleList::Iterator ndx = m_pEndTimeList->Begin();
for (; ndx != m_pEndTimeList->End(); ++ndx)
{
SmilTimeValue* pTV = (SmilTimeValue*)(*ndx);
HX_DELETE(pTV);
}
HX_DELETE(m_pEndTimeList);
}
HX_DELETE(m_pHyperlinks);
HX_DELETE(m_pTimelineElement);
HX_VECTOR_DELETE(m_pszClipBeginMarkerName);
HX_VECTOR_DELETE(m_pszClipBeginExternalMarkerFileName);
HX_VECTOR_DELETE(m_pszClipEndMarkerName);
HX_VECTOR_DELETE(m_pszClipEndExternalMarkerFileName);
}
void
CSmilElement::addDuration(UINT32 ulDuration)
{
// default add duration just attempts to add it to it's parent
m_ulDuration = ulDuration;
if(m_pNode->m_pParent && m_pNode->m_pParent->m_pElement)
{
m_pNode->m_pParent->m_pElement->addDuration(m_ulDuration);
m_bAddDurationAlreadyDone = TRUE;
}
}
void
CSmilElement::addElement(CSmilElement* pElement,
UINT32& ulBeginOffset, UINT32& ulDuration)
{
}
void
CSmilElement::prepForRestart(BOOL bParentIsRestarting, LONG32 lWhen)
{
m_bInsertedIntoTimeline = FALSE;
m_bRendererInitialized = FALSE;
m_bBeginOffsetSet = FALSE;
// /Reset these, too, or hiding of site will happen too early next time:
m_bCurBeginIsOffsetFromSyncBase = TRUE;
// /This seems to work fine in case where begin="x; y" where x is a
// clock value and y is an event-arc that resolves at/to a time prior
// to x. (The other option is to set m_bCurBeginIsOffsetFromSyncBase
// to FALSE when !m_bBeginOffsetSet):
m_ulBeginOffsetFromSyncBase = 0;
m_bNegBeginOffsetAlreadyUsed = FALSE;
m_ulClipBegin = m_ulAuthoredClipBegin;
m_bAddDurationAlreadyDone = FALSE;
// /XXXEH- TODO: test this!:
m_bDurationIncludesDelayBeyondSyncbase = FALSE;
m_bIsPausedInExcl = FALSE;
m_bIsDeferredInExcl = FALSE;
m_ulTimeDeferralOccurred = (UINT32)-1;
m_bIsStoppedInExcl = FALSE;
m_ulAnticipatedPauseDur = 0;
// /If we restart a source, the next play may be a different file, even
// live one time and on-demand the next, so reset this and let next call
// to TrackDurationSet() tell us if it's live this time:
m_bCurrentSourceIsLive = FALSE;
// /Adding this helps fix a lot of restart problems, including part of
// PR 62408 and par version of PR 50660. The playToAssoc was never
// removed when the track ended the first time, so the doc renderer
// (m_pHandler) used to see this track as already added and would
// erroneously add this restart as a repeat track:
m_bIsRestarting = TRUE;
// /Helps fix restart problems related to PR 55253:
if (bParentIsRestarting)
{
LONG32 lNextResolvedEndTime = 0;
BOOL bHasFutureResolvedEnd = FALSE;
if (m_bHasExplicitEnd)
{
SmilTimeValue* pNextResolvedEndTimeValue = NULL;
HX_RESULT rettimeval = HXR_OK;
// /lWhen must be in syncBase time space, not group time space:
rettimeval = getNextResolvedTimeValue(pNextResolvedEndTimeValue,
SMILTIME_NEGATIVE_INFINITY, lWhen, SmilEndTimeList, NULL);
if (SUCCEEDED(rettimeval) && NULL != pNextResolvedEndTimeValue)
{
HX_RESULT rtval = pNextResolvedEndTimeValue->
getEffectiveResolvedTime(lNextResolvedEndTime);
if (SUCCEEDED(rtval))
{
bHasFutureResolvedEnd = TRUE;
if (lWhen < lNextResolvedEndTime)
{
m_ulDuration = (UINT32)(lNextResolvedEndTime - lWhen);
}
}
}
}
if (m_bHasExplicitDur)
{
if (!bHasFutureResolvedEnd)
{
m_ulDuration = m_ulAuthoredDur;
}
else if (lNextResolvedEndTime - lWhen > (LONG32)m_ulAuthoredDur)
{
m_ulDuration = m_ulAuthoredDur;
}
}
else
{
// /Let SetDelay() and insertTimeline... deal with new duration:
m_ulDuration = (UINT32)-1;
}
}
// /Reset the delay since it will be new, obviously, for this restart;
// helps fix restart problems related to PR 56233:
m_ulDelay = (UINT32)-1;
// /Note: we don't want to or need to reset the delay here. A restart
// based on either a syncArc or eventArc will take care of that.
if (m_pTimelineElement)
{
m_pTimelineElement->prepForRestart();
}
// /Now, call this function for all descendants as well in case this is
// a time container (or a media object with timeline-element children);
// (Helps fix restart problems related to PR 55253)
SMILNode* pChild = m_pNode->getFirstChild();
while (pChild)
{
CSmilElement* pElement = pChild->m_pElement;
if (pElement && pElement->m_pHandler &&
pElement->m_bInsertedIntoTimeline)
{
pElement->prepForRestart(TRUE, lWhen);
}
pChild = m_pNode->getNextChild();
}
}
void
CSmilElement::prepForPauseInExcl(LONG32 lCurTime)
{
m_bIsPausedInExcl = TRUE;
// /If we're being set to paused state, then we need to adjust our hide
// event (removeTime) in concert with adjusting when we will end:
BOOL bHasFutureResolvedExplicitEnd = FALSE;
if (m_bHasExplicitEnd)
{
SmilTimeValue* pNextResolvedEndTimeValue = NULL;
HX_RESULT rettimeval = HXR_OK;
// /lCurTime must be in syncBase time space, not group time space:
rettimeval = getNextResolvedTimeValue(pNextResolvedEndTimeValue,
SMILTIME_NEGATIVE_INFINITY, lCurTime, SmilEndTimeList, NULL);
if (SUCCEEDED(rettimeval) && NULL != pNextResolvedEndTimeValue)
{
LONG32 lNextResolvedEndTime = SMILTIME_NEGATIVE_INFINITY;
HX_RESULT rtval = pNextResolvedEndTimeValue->
getEffectiveResolvedTime(lNextResolvedEndTime);
if (SUCCEEDED(rtval))
{
HX_ASSERT(lCurTime <= lNextResolvedEndTime);
bHasFutureResolvedExplicitEnd = TRUE;
updateRemoveTime(lNextResolvedEndTime);
}
}
}
// /If we don't have explicit end, then we'll end when we get resumed
// plus the remainder of our duration:
if (!bHasFutureResolvedExplicitEnd)
{
updateRemoveTime(SMILTIME_PAUSED_INDEFINITELY);
}
}
void
CSmilElement::prepForResumeInExcl()
{
HX_ASSERT(m_bIsPausedInExcl);
LISTPOSITION lPos = NULL;
HX_ASSERT(m_pBeginTimeList);
if (m_pBeginTimeList)
{
lPos = m_pBeginTimeList->GetHeadPosition();
}
while (lPos)
{
SmilTimeValue* pTimeVal =
(SmilTimeValue*)m_pBeginTimeList->GetAt(lPos);
// /There should be only one resumeEvent:
if (pTimeVal && pTimeVal->isResumeEvent())
{
// /Fixes PR 62408: remove resumeEvent from element's begin
// list since it was an internally-generated single-use begin
// value and we don't want it to re-resolve when (if) the
// original pausing element restarts and then raises another
// resumeEvent when it ends again:
m_pBeginTimeList->RemoveAt(lPos);
break;
}
m_pBeginTimeList->GetNext(lPos);
}
m_bIsPausedInExcl = FALSE;
}
void
CSmilElement::prepForStopInExcl(LONG32 lCurTime)
{
m_bIsStoppedInExcl = TRUE;
m_ulStopTimeInExcl = (ULONG32)lCurTime;
}
void
CSmilElement::prepForDeferralInExcl(UINT32 lCurTime)
{
m_ulTimeDeferralOccurred = lCurTime;
m_bIsDeferredInExcl = TRUE;
}
HX_RESULT
CSmilElement::setBeginTime(CSmilParser* pParser)
{
HX_RESULT ret = HXR_OK;
BOOL bBeginTimeHasBeenSet = FALSE;
UINT32 ulOffset = 0;
SmilTimeValue* pNextResolvedTimeValue = NULL;
LISTPOSITION lPos = NULL;
// /We need this so we can go through
CHXSimpleList* pListOfAllResolvedBeginTimes = new CHXSimpleList;
// /Looks at all resolved begin times in the list and
// returns the SmilTimeValue with the closest time at or
// later than the time passed in:
HX_RESULT rettimeval = HXR_OK;
rettimeval = getNextResolvedTimeValue(pNextResolvedTimeValue,
SMILTIME_NEGATIVE_INFINITY, SMILTIME_NEGATIVE_INFINITY,
SmilBeginTimeList, pListOfAllResolvedBeginTimes);
// /NOTE: ret!=HXR_OK is NOT an error condition; it means
// that no value in the begin time list was found that was
// resolved.
BOOL bIsDescendantOfExcl = pParser->hasAncestor(SMILExcl, m_pNode);
SMILNode* pSyncAncestor = pParser->getSyncAncestor(m_pNode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -