smlprstime.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,440 行 · 第 1/3 页
CPP
1,440 行
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: smlprstime.cpp,v 1.2.12.1 2004/07/09 01:58:02 hubbe 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>
#ifdef _UNIX
#include <ctype.h>
#endif
// include
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxxml.h"
#include "smiltype.h"
// pncont
#include "hxstring.h"
#include "hxslist.h"
// pnmisc
#include "nptime.h"
#include "smpte.h"
#include "hxwinver.h"
// rnxmllib
#include "hxxmlprs.h"
// rmasmil
#include "smlerror.h"
#include "smlparse.h"
#include "smlelem.h"
#include "smlprstime.h"
// pndebug
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
SmilTimeValue::SmilTimeValue(IUnknown* pContext, UINT32 ulStartLine,
CSmilElement* pElement)
: m_pContext(pContext)
, m_pElement(pElement)
, m_ulStartLine(ulStartLine)
, m_type(SmilTimeNone)
, m_position(SMILEventSourceEnd)
, m_uRepeatIteration(0)
, m_bTreatSyncArcAsEvent(FALSE)
, m_lOffset(0)
, m_lOriginalOffset(0)
, m_year(-1)
, m_month(-1)
, m_day(-1)
, m_hour(0)
, m_min(0)
, m_sec(0)
, m_ms(0)
, m_UTCOffsetMin(0)
, m_bRelativeToUTC(FALSE)
, m_pszMarkerName(NULL)
, m_bIsExternalMarker(FALSE)
, m_pszExternalMarkerFileName(NULL)
, m_pszExternalMarkerName(NULL)
, m_ulMarkerTime(0)
, m_bUsedToBeMediaMarker(FALSE)
, m_pEventName(NULL)
, m_bTimeIsResolved(FALSE)
, m_lResolvedToTime(SMILTIME_INFINITY)
, m_lWhenTimeWasResolved(SMILTIME_INFINITY)
, m_lTimeOfPause(SMILTIME_INFINITY)
{
m_pContext->AddRef();
}
SmilTimeValue::~SmilTimeValue()
{
HX_RELEASE(m_pContext); // /fixes mem leak.
HX_VECTOR_DELETE(m_pszMarkerName);
HX_VECTOR_DELETE(m_pszExternalMarkerFileName);
HX_VECTOR_DELETE(m_pszExternalMarkerName);
HX_VECTOR_DELETE(m_pEventName);
}
// /This returns the resolved time, including any positive offset,
// and includes only the part of a negative offset that is after
// the resolved-AT time (which is m_lWhenTimeWasResolved). In other
// words, this returns the time at which the element will actually
// begin or end based on this SmilTimeValue:
//
// Returns HXR_OK if resolved time is returned in lEffectiveResolveTime,
// else returns HXR_FAILED.
HX_RESULT
SmilTimeValue::getEffectiveResolvedTime(REF(INT32) lEffectiveResolvedTime)
{
HX_RESULT retval = HXR_OK;
lEffectiveResolvedTime = SMILTIME_NEGATIVE_INFINITY;
switch (m_type)
{
case SmilTimeSyncBase:
#if defined(ENABLE_SYNC_TO_PREV)
case SmilTimeSyncToPrev:
#endif
case SmilTimeMediaMarker:
case SmilTimeEvent:
{
if (isTimeResolved())
{
// /EH- the following should *always* be true:
HX_ASSERT(m_lResolvedToTime >= m_lWhenTimeWasResolved);
// /Note: resolvedToTime doesn't include offset:
lEffectiveResolvedTime = m_lResolvedToTime;
#define XXXEH_OFFSET_NOT_ALREADY_ACCOUNTED_FOR
#if defined(XXXEH_OFFSET_NOT_ALREADY_ACCOUNTED_FOR)
if (SmilTimeEvent == m_type
// /XXXEH- TODO: handle SmilTimeMediaMarker here, too,
// if and when we get internal markers (event-like
// ones) working:
|| (isSyncBaseTimeVal() && m_bTreatSyncArcAsEvent))
{
INT32 lEffectiveOffset = m_lOffset;
if (lEffectiveOffset < 0)
{
lEffectiveOffset = m_lWhenTimeWasResolved -
m_lResolvedToTime;
if (lEffectiveOffset < m_lOffset)
{
// /Resolved-at time was well before resolved-to
// time minus |offset|, so the entire offset is
// used:
lEffectiveOffset = m_lOffset;
}
}
lEffectiveResolvedTime += lEffectiveOffset;
}
#endif
}
else
{
retval = HXR_FAILED;
}
}
break;
// /XXXEH- TODO: figure out how to handle wallclock; I think
// it should just work the same as clock values:
case SmilTimeWallclock:
case SmilTimeClockValue:
case SmilTimeOffset:
{
if (isTimeResolved())
{
lEffectiveResolvedTime = m_lOffset;
}
else
{
retval = HXR_FAILED;
// /All wallclock, clock, and offset values should have
// been set as resolved at parse time:
HX_ASSERT(isTimeResolved());
}
}
break;
default:
{
retval = HXR_FAILED;
}
break;
}
return retval;
}
HX_RESULT
SmilTimeValue::parseValue(const char* pPos,
SMILSyncAttributeTag nTag,
// /Needed for self-references:
const char* pThisElementID)
{
HX_RESULT ret = HXR_OK;
if (pPos == (const char*)NULL)
{
ret = HXR_FAIL;
}
else if (*pPos == '+' || *pPos == '-')
{
HX_ASSERT(nTag == SMILSyncAttrBegin);
if (nTag == SMILSyncAttrBegin)
{
ret = parseOffset(pPos);
m_type = SmilTimeOffset;
if (SUCCEEDED(ret))
{
m_bTimeIsResolved = TRUE;
}
}
else
{
CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
errHandler.ReportError(SMILErrorBadTimeValue, pPos,
m_ulStartLine);
return ret;
}
}
else if (isdigit(*pPos)
// /Fixes PR 42592:
// "0.5s" was OK but ".5s" was being treated as unresolved:
|| '.' == *pPos)
{
ret = parseOffset(pPos);
if (SUCCEEDED(ret))
{
m_bTimeIsResolved = TRUE;
}
// this is actually a Clock Value if it is an end
// time.
if (nTag == SMILSyncAttrBegin)
{
m_type = SmilTimeOffset;
}
else // nTag == SMILSyncAttrEnd
{
m_type = SmilTimeClockValue;
}
}
#if defined(ENABLE_SYNC_TO_PREV)
else if (strncmp(pPos, "prev", 4) == 0)
{
// syncToPrev-value
ret = parseSyncToPrev(pPos);
}
#endif
else if (strncmp(pPos, "wallclock", 9) == 0)
{
// wallclock-sync-value
ret = parseWallClockValue(pPos);
}
else
{
const char* pDotPos = NULL;
BOOL bEscape = FALSE;
UINT32 len = strlen(pPos);
char* idref = new char [len+1];
char* idrefPos = idref;
*idrefPos = '\0';
char* command = new char [len+1];
char* commandPos = command;
*commandPos = '\0';
const char* pOffset = NULL;
enum { IDREF, ESCAPE, COMMAND, END, OFFSET } state = IDREF;
const char* pBegin = pPos;
while (*pPos)
{
switch (state)
{
case ESCAPE:
*idrefPos++ = *pPos;
state = IDREF;
break;
case IDREF:
if (*pPos == '\\')
{
// /Don't include escape char in idref; go to next char:
state = ESCAPE;
}
else if (*pPos == '.')
{
*idrefPos = '\0';
state = COMMAND;
}
else if (isspace(*pPos))
{
*idrefPos = '\0';
state = END;
}
else if (*pPos == '+' || *pPos == '-')
{
*idrefPos++ = '\0';
pOffset = pPos;
state = OFFSET;
}
else
{
*idrefPos++ = *pPos;
}
break;
case COMMAND:
if (isspace(*pPos))
{
*commandPos = '\0';
state = END;
}
else if (*pPos == '+' || *pPos == '-')
{
pOffset = pPos;
*commandPos = '\0';
state = OFFSET;
}
else
{
*commandPos++ = *pPos;
}
break;
case END:
if (*pPos == '+' || *pPos == '-')
{
pOffset = pPos;
state = OFFSET;
}
break;
case OFFSET:
break;
}
++pPos;
}
if (state == COMMAND)
{
*commandPos = '\0';
}
else if (state == IDREF || state == ESCAPE)
{
*idrefPos = '\0';
}
// XXXMEH - if this is an animation element, then we
// will handle the ".repeat(x)" syntax differently than
// we treat sources. We will treat ".repeat(x)" as an
// event rather than a sync-arc.
BOOL bIsAnimate = FALSE;
if (m_pElement && m_pElement->m_pNode &&
(m_pElement->m_pNode->m_tag == SMILAnimate ||
m_pElement->m_pNode->m_tag == SMILSet ||
m_pElement->m_pNode->m_tag == SMILAnimateMotion ||
m_pElement->m_pNode->m_tag == SMILAnimateColor))
{
bIsAnimate = TRUE;
}
if (*command == '\0')
{
// /The SMIL Boston draft supports the fact that the name of the
// event ("Event-symbol") is required and is what is used when
// no "Eventbase-element." precedes it. Thus, we need to
// treat the idref as the command string and use this
// element's id for the idref:
// /HOWEVER, for PR 69849 (needed for PR 58290) fix, if event is
// "accesskey(...)", then the event is not self-generated and is
// not raised for another element, so give it a fake id here so
// special-case code isn't needed in multiple places, elsewhere:
if (!strncmp(idref, "accesskey(", 10))
{
ret = parseEvent(
// /Use this string (an invalid XML id) as the fake ID:
ACCESSKEY_EVENT_FAKE_ID_STRING, // /fake ID.
idref, // /<==actually the command (i.e., Event-symbol)
pOffset);
}
else
{
ret = parseEvent(pThisElementID,
idref, // /<==actually the command (i.e., Event-symbol)
pOffset);
}
}
else if (strcmp(command, "begin") == 0 ||
#if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
#else
((0 == strncmp(command, "repeat(", 7)) && !bIsAnimate) ||
#endif
strcmp(command, "end") == 0)
{
// base, memeber, offset
ret = parseSyncBase(idref, command, pOffset);
}
else if (strncmp(command, "marker(", 7) == 0)
{
ret = parseMarker(idref, command, pOffset);
}
else // /everything else is an event (i.e., "Event-symbol") name:
{
ret = parseEvent(idref, command, pOffset);
}
HX_VECTOR_DELETE(command);
HX_VECTOR_DELETE(idref);
}
// /We need to make sure we set scheduled time values' resolved-to times
// in case these times are used AFTER the element has already begun
// playing or finished playing:
if (SmilTimeOffset == m_type ||
SmilTimeClockValue == m_type ||
SmilTimeWallclock == m_type)
{
setResolvedToTime(0);
setWhenTimeWasResolved(0);
}
return ret;
}
HX_RESULT
SmilTimeValue::setTimeOffset(time_t tRefTime)
{
HX_RESULT ret = HXR_OK;
if (m_type == SmilTimeWallclock)
{
struct tm ourtime;
ourtime.tm_sec = m_sec;
ourtime.tm_min = m_min;
ourtime.tm_hour = m_hour;
if (m_day != -1 && m_year != -1 && m_month != -1)
{
ourtime.tm_mday = m_day;
// /tm::tm_mon is 0-based, while m_month is 1-based, so we need
// to subtract 1 (and our parser already made sure m_month is
// greater than 0 and less than 13):
ourtime.tm_mon = m_month - 1;
ourtime.tm_year = m_year - 1900;
}
else
{
time_t thetime;
time(&thetime);
struct tm* cur;
cur = localtime(&thetime);
ourtime.tm_mday = cur->tm_mday;
ourtime.tm_mon = cur->tm_mon;
ourtime.tm_year = cur->tm_year;
ourtime.tm_isdst = cur->tm_isdst;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?