smlprstime.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:35k
- /* ***** 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>
- #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 = ' ';
- char* command = new char [len+1];
- char* commandPos = command;
- *commandPos = ' ';
- 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 = ' ';
- state = COMMAND;
- }
- else if (isspace(*pPos))
- {
- *idrefPos = ' ';
- state = END;
- }
- else if (*pPos == '+' || *pPos == '-')
- {
- *idrefPos++ = ' ';
- pOffset = pPos;
- state = OFFSET;
- }
- else
- {
- *idrefPos++ = *pPos;
- }
- break;
- case COMMAND:
- if (isspace(*pPos))
- {
- *commandPos = ' ';
- state = END;
- }
- else if (*pPos == '+' || *pPos == '-')
- {
- pOffset = pPos;
- *commandPos = ' ';
- state = OFFSET;
- }
- else
- {
- *commandPos++ = *pPos;
- }
- break;
- case END:
- if (*pPos == '+' || *pPos == '-')
- {
- pOffset = pPos;
- state = OFFSET;
- }
- break;
- case OFFSET:
- break;
- }
- ++pPos;
- }
- if (state == COMMAND)
- {
- *commandPos = ' ';
- }
- else if (state == IDREF || state == ESCAPE)
- {
- *idrefPos = ' ';
- }
- // 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 == ' ')
- {
- // /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;
- }
- time_t thisTime = mktime(&ourtime);
- double diff = 0.0;
- if (m_bRelativeToUTC)
- {
- //XXXJHUG need a crossplatform way to get the timezone offset.
- #ifdef _WIN32
- diff = difftime(thisTime + _timezone, tRefTime + m_UTCOffsetMin);
- #else
- diff = difftime(thisTime, tRefTime + m_UTCOffsetMin);
- #endif
- }
- else
- {
- diff = difftime(thisTime, tRefTime);
- }
- double dDiffMS = diff * 1000.0;
- double dMaxDiff = (double) 0x7FFFFFFF;
- double dMinDiff = -dMaxDiff;
- // Clip at the min and max
- if (dDiffMS > dMaxDiff)
- {
- dDiffMS = dMaxDiff - 10;
- }
- else if (dDiffMS < dMinDiff)
- {
- dDiffMS = dMinDiff +10;
- }
- // Now convert to INT32
- m_lOffset = (INT32) dDiffMS;
- m_lOriginalOffset = m_lOffset;
- }
- return ret;
- }
- HX_RESULT
- SmilTimeValue::parseOffset(const char* pCh)
- {
- HX_RESULT pnretval = HXR_OK;
- // eat whitespace
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == '-')
- {
- // /Eat any whitespace following the '-'
- do
- {
- ++pCh;
- } while (*pCh && isspace(*pCh));
- UINT32 clockTime = 0;
- pnretval = parseClockValue(pCh, clockTime);
- m_lOffset = -(INT32)clockTime;
- }
- else if (*pCh == '+')
- {
- // /Eat any whitespace following the '+'
- do
- {
- ++pCh;
- } while (*pCh && isspace(*pCh));
- UINT32 clockTime = 0;
- pnretval = parseClockValue(pCh, clockTime);
- m_lOffset = (INT32)clockTime;
- }
- else
- {
- UINT32 clockTime = 0;
- pnretval = parseClockValue(pCh, clockTime);
- m_lOffset = (INT32)clockTime;
- }
- m_lOriginalOffset = m_lOffset;
- return pnretval;
- }
- HX_RESULT
- SmilTimeValue::parseClockValue(const char* pValue,
- UINT32& ulTimeValue)
- {
- if (!pValue || strlen(pValue) < 1)
- {
- return HXR_FAILED;
- }
- // try npt
- char* pPtr = (char *)strstr(pValue, "npt=");
- if(pPtr)
- {
- pPtr += 4; // point to beginning of clock value
- NPTime clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- // try smpte
- pPtr = (char *)strstr(pValue, "smpte=");
- if(pPtr)
- {
- pPtr += 6; // point to beginning of clock value
- SMPTETimeCode clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- pPtr = (char *)strstr(pValue, "smpte-30-drop=");
- if(pPtr)
- {
- pPtr += 14; // point to beginning of clock value
- SMPTETimeCode clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- pPtr = (char *)strstr(pValue, "smpte-25=");
- if(pPtr)
- {
- pPtr += 9; // point to beginning of clock value
- SMPTETimeCode clockTime;
- clockTime.m_framesPerSec = SMPTETimeCode::FPS_25;
- clockTime.fromString(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- else
- {
- BOOL bAllow_h_min_s_ms_units = TRUE;
- BOOL bSucceeded = FALSE;
- // /First, get rid of trailing spaces:
- UINT32 ulStrlen = (UINT32)strlen(pValue);
- char* pEnd = (char*)(&pValue[ulStrlen-1]);
- while (isspace(*pEnd) && pEnd>pValue)
- {
- pEnd--;
- }
- pEnd[1] = ' ';
- // /This first tries just hh:mm:ss with no prefix/suffix
- // and then tries suffixes: {"h" | "min" | "s" | "ms"} with
- // the default (no ":" inside and no prefix or suffix) being
- // in seconds per the SMIL 1.0 spec ([SMIL 1.0 compliance]
- // Fixes PR 22673):
- NPTime clockTime(pValue, bAllow_h_min_s_ms_units, bSucceeded);
- if (bSucceeded)
- {
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- }
- return HXR_FAIL;
- }
- HX_RESULT
- SmilTimeValue::parseEvent(const char* pBase, const char* pEvent,
- const char* pOffset)
- {
- HX_RESULT rslt = HXR_OK;
- m_type = SmilTimeEvent;
- UINT32 ulLen = 0;
- if (pBase)
- {
- ulLen = strlen(pBase);
- m_idRef = pBase;
- }
-
- if( !pEvent || !strlen(pEvent))
- {
- // /XXXEH- not sure why we'd ever get this state so put assert here
- // to check it out:
- HX_ASSERT(pEvent && strlen(pEvent));
- m_pEventName = NULL;
- rslt = HXR_UNEXPECTED; // /XXXEH- at least I *think* it's unexpected.
- }
- else
- {
- // /Handle "foo.xyz" as meaning the "xyz" event that may have the
- // same name as a sync-arc, e.g., "foo.begin". Treat them as
- // events that get resolved when the m_idRef element (renderer)
- // fires off a an event with the matching name:
- if ('\' == *pEvent && strlen(pEvent)>=2)
- {
- // /Add -1 for removing the '', +1 for the terminating ' ':
- m_pEventName = new char[strlen(pEvent)-1 + 1];
- if (m_pEventName)
- {
- strcpy(m_pEventName, &pEvent[1]); /* Flawfinder: ignore */
- }
- else
- {
- rslt = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- m_pEventName = new char[strlen(pEvent)+1];
- if (m_pEventName)
- {
- strcpy(m_pEventName, pEvent); /* Flawfinder: ignore */
- }
- else
- {
- rslt = HXR_OUTOFMEMORY;
- }
- }
- }
- if (SUCCEEDED(rslt) && pOffset && *pOffset)
- {
- parseOffset(pOffset);
- }
- return rslt;
- }
- HX_RESULT
- SmilTimeValue::parseSyncBase(const char* pBase, const char* pCommand,
- const char* pOffset)
- {
- m_type = SmilTimeSyncBase;
- UINT32 ulLen = strlen(pBase);
- if (pBase && pCommand)
- {
- m_idRef = pBase;
- }
- else
- {
- HX_ASSERT(FALSE);
- return HXR_FAIL;
- }
- BOOL bTimeValueOK = FALSE;
- BOOL bRepeatValueParsed = FALSE;
- if (strncmp(pCommand, "begin", 5) == 0)
- {
- m_position = SMILEventSourceBegin;
- bTimeValueOK = TRUE;
- }
- else if (strncmp(pCommand, "end", 3) == 0)
- {
- m_position = SMILEventSourceEnd;
- bTimeValueOK = TRUE;
- }
- #if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
- #else
- else if (strncmp(pCommand, "repeat(", 7) == 0)
- {
- bRepeatValueParsed = TRUE;
- INT32 strlenCommand = strlen(pCommand);
- if (strlenCommand >= 9 && ')' == pCommand[strlenCommand-1])
- {
- m_position = SMILEventSourceBegin;
- char* pTmp = (char*)&pCommand[7];
- // /Make sure that every character inside the () is a number:
- while (*pTmp && ')' != *pTmp && '0'<=*pTmp && '9'>=*pTmp)
- {
- pTmp++;
- }
- if (pTmp == (char*)&pCommand[strlenCommand-1])
- {
- INT32 lNum = (INT32)atoi(&pCommand[7]);
- // /0 or negative repeat iterations are not allowed, even
- // though repeat(0) *could* have been interpreted as the
- // first play of foo (prior to it repeating), but wasn't:
- if (lNum > 0)
- {
- *pTmp = ' ';
- m_idRef += "_repeat_copy_";
- m_idRef += &pCommand[7];
- *pTmp = ')'; // /restore it.
- m_uRepeatIteration = (UINT16)lNum;
- bTimeValueOK = TRUE;
- }
- }
- }
- }
- #endif
- if (!bTimeValueOK)
- {
- if (!bRepeatValueParsed)
- {
- HX_ASSERT(FALSE);
- }
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadTimeValue, pCommand,
- m_ulStartLine);
- return HXR_FAIL;
- }
- if (pOffset)
- {
- parseOffset(pOffset);
- }
- return HXR_OK;
- }
- HX_RESULT SmilTimeValue::parseMarker(const char* pBase, const char* pMarker, const char* pOffset)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pBase && pMarker)
- {
- // Set the type
- m_type = SmilTimeMediaMarker;
- // Set the base
- m_idRef = pBase;
- // Set the offset (if we have one)
- if (pOffset)
- {
- parseOffset(pOffset);
- }
- // Move past the "marker.(", which we already
- // checked for before we were called
- pMarker += 7;
- // Allocate space for our string
- HX_VECTOR_DELETE(m_pszMarkerName);
- m_pszMarkerName = new char [strlen(pMarker) + 1];
- if (m_pszMarkerName)
- {
- // Look for the end of the marker name
- char* pEnd = (char *)strchr(pMarker, ')');
- if (pEnd)
- {
- // Copy the full marker name - might or
- // might not contain an external file reference
- strncpy(m_pszMarkerName, pMarker, pEnd - pMarker); /* Flawfinder: ignore */
- m_pszMarkerName[pEnd - pMarker] = ' ';
- // Now parse to see if there is an external file reference
- CHXString cMarker;
- CHXString cExtFileName;
- BOOL bIsExternalMarker = m_bIsExternalMarker;
- retVal = CSmilParser::parseMarkerURI(m_pszMarkerName,
- cMarker,
- bIsExternalMarker,
- cExtFileName);
- m_bIsExternalMarker = bIsExternalMarker;
- if (SUCCEEDED(retVal) && m_bIsExternalMarker)
- {
- // Set the flag in the element that this
- // element references an external media marker file
- m_pElement->m_bUsesExternalMediaMarkerFile = TRUE;
- // We just need to copy the marker string and
- // the external file name string into our members
- HX_VECTOR_DELETE(m_pszExternalMarkerFileName);
- m_pszExternalMarkerFileName = new char [cExtFileName.GetLength() + 1];
- if (m_pszExternalMarkerFileName)
- {
- strcpy(m_pszExternalMarkerFileName, (const char*) cExtFileName); /* Flawfinder: ignore */
- HX_VECTOR_DELETE(m_pszExternalMarkerName);
- m_pszExternalMarkerName = new char [cMarker.GetLength() + 1];
- if (m_pszExternalMarkerName)
- {
- strcpy(m_pszExternalMarkerName, (const char*) cMarker); /* Flawfinder: ignore */
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- else
- {
- retVal = HXR_OUTOFMEMORY;
- }
- }
- }
- }
- }
- if (FAILED(retVal))
- {
- HX_ASSERT(FALSE);
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadTimeValue, pMarker, m_ulStartLine);
- }
- return retVal;
- }
- #if defined(ENABLE_SYNC_TO_PREV)
- HX_RESULT
- SmilTimeValue::parseSyncToPrev(REF(const char*) pCh)
- {
- HX_RESULT ret = HXR_OK;
- // move past "prev."
- pCh += 5;
- m_type = SmilTimeSyncToPrev;
- if (strncmp(pCh, "begin", 5) == 0)
- {
- m_position = SMILEventSourceBegin;
- pCh += 5;
- }
- else if (strncmp(pCh, "end", 3) == 0)
- {
- m_position = SMILEventSourceEnd;
- pCh += 3;
- }
- else
- {
- HX_ASSERT(FALSE);
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadTimeValue, pCh,
- m_ulStartLine);
- return HXR_FAIL;
- }
- // eat white space
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == '+' || *pCh == '-')
- {
- ret = parseOffset(pCh);
- }
-
- return ret;
- }
- #endif
- HX_RESULT
- SmilTimeValue::parseWallClockValue(REF(const char*) pCh)
- {
- HX_RESULT ret = HXR_OK;
- m_type = SmilTimeWallclock;
- m_bTimeIsResolved = TRUE;
- // move past "wallclock("
- pCh += 10;
- // eat whitespace.
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- // find the end ')'
- const char* begin = pCh;
- const char* end = NULL;
- const char* pT = NULL;
- const char* pTimeZone = NULL;
- const char* pTimePos = NULL;
- const char* pDatePos = NULL;
- INT32 year = -1;
- INT32 month = -1;
- INT32 day = -1;
- INT32 hour = 0;
- INT32 min = 0;
- INT32 sec = 0;
- INT32 ms = 0;
- char buf[10]; /* Flawfinder: ignore */
-
- // store offset in min.
- INT32 UTCOffset = 0;
- while (*pCh)
- {
- if (*pCh == ')')
- {
- end = pCh;
- }
- else if (*pCh == 'T')
- {
- pT = pCh;
- }
- else if (isspace(*pCh) || *pCh == '+' || *pCh == '-' || *pCh == 'Z')
- {
- // this will find the last +, - or Z... which is what we want.
- pTimeZone = pCh;
- }
- else if (!isdigit(*pCh) && *pCh != ':' && *pCh != '-' && *pCh != '.')
- {
- ret = HXR_FAIL;
- }
- ++pCh;
- }
- if (FAILED(ret))
- {
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- // check for a 'T'
- if (pT)
- {
- //YYYY-MM-DDT
- if (*(begin+4) == '-' && *(begin+7) == '-' && pT == (begin+10))
- {
- pDatePos = begin;
- if (pTimeZone < begin+10)
- {
- pTimeZone = NULL;
- }
- }
- else
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- if (*(pT+3) == ':')
- {
- pTimePos = pT+1;
- }
- else
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- }
- // else just the date or time.
- //YYYY-MM-DDT
- else if (*(begin+4) == '-' && *(begin+7) == '-' && pT == (begin+10))
- {
- // just date
- // there is a date.
- pDatePos = begin;
- if (pTimeZone < begin+10)
- {
- pTimeZone = NULL;
- }
- }
- else if (*(begin+2) == ':')
- {
- pTimePos = begin;
- }
- else
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- // there is a date.
- if (pDatePos)
- {
- //YYYY-MM-DDT
- const char* pos = pDatePos;
- strncpy(buf, pos, 4); /* Flawfinder: ignore */
- buf[4] = ' ';
- pos += 5;
- year = HX_SAFEINT(strtol(buf, 0, 10));
- if (year < 0 || year > 9999)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos,
- m_ulStartLine);
- goto cleanup;
- }
- strncpy(buf, pos, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pos += 3;
- month = HX_SAFEINT(strtol(buf, 0, 10));
- // /month can't be 0 or less or greater than 12 (i.e., it's
- // 1-based):
- if (month < 1 || month > 12)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos,
- m_ulStartLine);
- goto cleanup;
- }
- strncpy(buf, pos, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pos += 3;
- day = HX_SAFEINT(strtol(buf, 0, 10));
- if (day < 0 || day > 31)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos,
- m_ulStartLine);
- goto cleanup;
- }
- }
- if (pTimePos)
- {
- //HH:MM...
- const char* pos = pTimePos;
- strncpy(buf, pos, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pos += 3;
- hour = HX_SAFEINT(strtol(buf, 0, 10));
- if (hour < 0 || hour > 24)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos,
- m_ulStartLine);
- goto cleanup;
- }
- // just time
- strncpy(buf, pos, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pos += 3;
- min = HX_SAFEINT(strtol(buf, 0, 10));
- if (min < 0 || min > 59)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos,
- m_ulStartLine);
- goto cleanup;
- }
- if (*(pos-1) == ':')
- {
- strncpy(buf, pos, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pos +=3;
- sec = HX_SAFEINT(strtol(buf, 0, 10));
- if (sec < 0 || sec > 59)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos,
- m_ulStartLine);
- goto cleanup;
- }
- if (*(pos-1) == '.')
- {
- // find end.
- UINT32 len = 0;
- if (pTimeZone)
- {
- len = pTimeZone - pos;
- }
- else
- {
- len = end - pos;
- }
- strncpy(buf, pos, len); /* Flawfinder: ignore */
- buf[len] = ' ';
- pos += len;
- if (*buf)
- {
- if (isdigit(*buf))
- {
- ms = (*buf - '0') * 100;
- if (isdigit(*(buf+1)))
- {
- ms += (*buf - '0') * 10;
- if (isdigit(*(buf+2)))
- {
- ms += (*buf - '0');
- }
- }
- }
- else
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos,
- m_ulStartLine);
- goto cleanup;
- }
- }
- }
- }
- }
- if (pTimeZone)
- {
- BOOL bSyntaxOK = FALSE;
- const char* begin = pTimeZone;
- if (*pTimeZone == 'Z')
- {
- m_bRelativeToUTC = TRUE;
- UTCOffset = 0;
- bSyntaxOK = TRUE;
- }
- else if ((*pTimeZone == '+' || *pTimeZone == '-') && *(pTimeZone+3) == ':')
- {
- m_bRelativeToUTC = TRUE;
- int sign = 1;
- if (*pTimeZone == '-')
- {
- ++pTimeZone;
- sign = -1;
- }
- else if (*pTimeZone == '+')
- {
- ++pTimeZone;
- }
- strncpy(buf, pTimeZone, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pTimeZone += 3;
- INT32 hour = HX_SAFEINT(strtol(buf, 0, 10));
- if (hour < 0 || hour > 12)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- UTCOffset = hour * 60;
- strncpy(buf, pTimeZone, 2); /* Flawfinder: ignore */
- buf[2] = ' ';
- pTimeZone += 3;
- INT32 min = HX_SAFEINT(strtol(buf, 0, 10));
- if (min < 0 || min > 59)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- UTCOffset += min;
- UTCOffset *= sign;
- bSyntaxOK = TRUE;
- }
- else if (isspace(*pTimeZone))
- {
- bSyntaxOK = TRUE;
- do
- {
- *pTimeZone++;
- if (!(*pTimeZone) || ')' == *pTimeZone)
- {
- break;
- }
- if (!isspace(*pTimeZone))
- {
- bSyntaxOK = FALSE;
- break;
- }
- } while (*pTimeZone);
- }
- if (!bSyntaxOK)
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadWallClockValue, begin,
- m_ulStartLine);
- goto cleanup;
- }
- }
- // else use the -1 value.
- m_UTCOffsetMin = (INT16)UTCOffset;
- m_ms = (UINT16)ms;
- m_sec = (UINT8)sec;
- m_min = (UINT8)min;
- m_hour = (UINT8)hour;
- m_day = (INT8)day;
- m_month = (INT8)month;
- m_year = (INT16)year;
- cleanup:
- if (SUCCEEDED(ret))
- {
- m_bTimeIsResolved = TRUE;
- }
- return ret;
- }
- void SmilTimeValue::setIsTimeResolved(BOOL bIsResolved)
- {
- m_bTimeIsResolved = bIsResolved;
- }
- HX_RESULT
- SmilTimeValue::setPauseTime(LONG32 lTimeOfPause)
- {
- HX_RESULT pnr = HXR_OK;
- if (!isResumeEvent())
- {
- pnr = HXR_UNEXPECTED;
- }
- else
- {
- m_lTimeOfPause = lTimeOfPause;
- }
- return pnr;
- }
- BOOL
- SmilTimeValue::isSameTimeValue(SmilTimeValue* pOtherTimeVal)
- {
- BOOL bIsSame = FALSE;
- // /Using this fixes freeze-up in use of strcmp(NULL,...) [PR 65817]
- // found while fixing Interop Timing #18.37 which has begin="0s;7s" :
- BOOL bHasSameEventNameOrBothHaveNoEventName =
- (NULL == m_pEventName && NULL == pOtherTimeVal->m_pEventName);
- if (!bHasSameEventNameOrBothHaveNoEventName)
- {
- if (NULL != m_pEventName && NULL != pOtherTimeVal->m_pEventName)
- {
- bHasSameEventNameOrBothHaveNoEventName =
- !strcmp(m_pEventName, pOtherTimeVal->m_pEventName);
- }
- }
- // /Now compare type, timing, event name, ...etc:
- if (pOtherTimeVal == this)
- {
- bIsSame = TRUE;
- }
- else if (pOtherTimeVal &&
- m_pElement == pOtherTimeVal->m_pElement &&
- m_type == pOtherTimeVal->m_type &&
- m_position == pOtherTimeVal->m_position &&
- m_uRepeatIteration == pOtherTimeVal->m_uRepeatIteration &&
- m_pszMarkerName == pOtherTimeVal->m_pszMarkerName &&
- bHasSameEventNameOrBothHaveNoEventName &&
- m_lOffset == pOtherTimeVal->m_lOffset &&
- m_bTimeIsResolved == pOtherTimeVal->m_bTimeIsResolved)
- {
- // /Note: if time isn't resolved, we don't care if times are same:
- if (m_bTimeIsResolved &&
- m_lResolvedToTime == pOtherTimeVal->m_lResolvedToTime)
- {
- bIsSame = TRUE;
- }
- else
- {
- switch (m_type)
- {
- case SmilTimeOffset:
- case SmilTimeClockValue:
- case SmilTimeWallclock:
- case SmilTimeNone:
- {
- bIsSame = TRUE;
- }
- break;
- case SmilTimeSyncBase:
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- #endif
- case SmilTimeMediaMarker:
- case SmilTimeEvent:
- {
- HX_ASSERT(m_idRef.GetLength());
- HX_ASSERT(pOtherTimeVal->m_idRef.GetLength());
- bIsSame = !strcmp(m_idRef, pOtherTimeVal->m_idRef);
- }
- break;
- }
- }
- }
- return bIsSame;
- }
- BOOL
- SmilTimeValue::deferUntil(LONG32 lNewStartTime)
- {
- BOOL bSucceeded = FALSE;
- if (m_bTimeIsResolved && m_lResolvedToTime < lNewStartTime)
- {
- // /XXXEH- TODO: determine if it's necessary to have a separate
- // variable that keeps track of the deferred amount, and that is
- // reset to 0 if and when this time is used to begin the element.
- // This might be needed if this SmilTimeValue gets reused due to
- // a repeat, seek, or ???
- switch (m_type)
- {
- case SmilTimeWallclock:
- case SmilTimeClockValue:
- case SmilTimeOffset:
- {
- // /Fixes PR 55936. Add the amount deferred by to the
- // offset instead of just setting offset to newStartTime:
- m_lOffset += (lNewStartTime - m_lResolvedToTime);
- bSucceeded = TRUE;
- }
- break;
- case SmilTimeSyncBase:
- #if defined(ENABLE_SYNC_TO_PREV)
- case SmilTimeSyncToPrev:
- #endif
- case SmilTimeMediaMarker:
- case SmilTimeEvent:
- {
- m_lResolvedToTime = lNewStartTime;
- bSucceeded = TRUE;
- }
- break;
- default:
- HX_ASSERT(0);
- break;
- }
- }
- return (bSucceeded);
- }
- void SmilTimeValue::setMarkerTime(UINT32 ulTime)
- {
- // Only do this if either we aren't resolved
- if (!m_bTimeIsResolved && m_type == SmilTimeMediaMarker)
- {
- // Save our marker time
- m_ulMarkerTime = ulTime;
- // This time is an offset from the beginning
- // of the media. We need to add this offset to
- // any previously existing offset
- m_lOffset += (INT32) ulTime;
- // Convert ourselves to a syncbase and
- // set the flag which will tell us that
- // we used to be a media marker.
- m_type = SmilTimeSyncBase;
- m_bUsedToBeMediaMarker = TRUE;
- // By definition we are an offset from the beginning
- // of the media
- m_position = SMILEventSourceBegin;
- // Set the flag saying we are resolved
- m_bTimeIsResolved = TRUE;
- }
- }