smlprstime.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:36k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: smlprstime.cpp,v 1.2.12.1 2004/07/09 01:58:02 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. // system
  50. #include <time.h>
  51. #ifdef _UNIX
  52. #include <ctype.h>
  53. #endif
  54. // include
  55. #include "hxtypes.h"
  56. #include "hxwintyp.h"
  57. #include "hxcom.h"
  58. #include "hxxml.h"
  59. #include "smiltype.h"
  60. // pncont
  61. #include "hxstring.h"
  62. #include "hxslist.h"
  63. // pnmisc
  64. #include "nptime.h"
  65. #include "smpte.h"
  66. #include "hxwinver.h"
  67. // rnxmllib
  68. #include "hxxmlprs.h"
  69. // rmasmil
  70. #include "smlerror.h"
  71. #include "smlparse.h"
  72. #include "smlelem.h"
  73. #include "smlprstime.h"
  74. // pndebug
  75. #include "hxheap.h"
  76. #ifdef _DEBUG
  77. #undef HX_THIS_FILE
  78. static const char HX_THIS_FILE[] = __FILE__;
  79. #endif
  80. SmilTimeValue::SmilTimeValue(IUnknown* pContext, UINT32 ulStartLine,
  81.      CSmilElement* pElement)
  82. : m_pContext(pContext)
  83. , m_pElement(pElement)
  84. , m_ulStartLine(ulStartLine)
  85. , m_type(SmilTimeNone)
  86. , m_position(SMILEventSourceEnd)
  87. , m_uRepeatIteration(0)
  88. , m_bTreatSyncArcAsEvent(FALSE)
  89. , m_lOffset(0)
  90. , m_lOriginalOffset(0)
  91. , m_year(-1)
  92. , m_month(-1)
  93. , m_day(-1)
  94. , m_hour(0)
  95. , m_min(0)
  96. , m_sec(0)
  97. , m_ms(0)
  98. , m_UTCOffsetMin(0)
  99. , m_bRelativeToUTC(FALSE)
  100. , m_pszMarkerName(NULL)
  101. , m_bIsExternalMarker(FALSE)
  102. , m_pszExternalMarkerFileName(NULL)
  103. , m_pszExternalMarkerName(NULL)
  104. , m_ulMarkerTime(0)
  105. , m_bUsedToBeMediaMarker(FALSE)
  106. , m_pEventName(NULL)
  107. , m_bTimeIsResolved(FALSE)
  108. , m_lResolvedToTime(SMILTIME_INFINITY)
  109. , m_lWhenTimeWasResolved(SMILTIME_INFINITY)
  110. , m_lTimeOfPause(SMILTIME_INFINITY)
  111. {
  112.     m_pContext->AddRef();
  113. }
  114. SmilTimeValue::~SmilTimeValue()
  115. {
  116.     HX_RELEASE(m_pContext); // /fixes mem leak.
  117.     HX_VECTOR_DELETE(m_pszMarkerName);
  118.     HX_VECTOR_DELETE(m_pszExternalMarkerFileName);
  119.     HX_VECTOR_DELETE(m_pszExternalMarkerName);
  120.     HX_VECTOR_DELETE(m_pEventName);
  121. }
  122. // /This returns the resolved time, including any positive offset,
  123. // and includes only the part of a negative offset that is after
  124. // the resolved-AT time (which is m_lWhenTimeWasResolved).  In other
  125. // words, this returns the time at which the element will actually
  126. // begin or end based on this SmilTimeValue:
  127. //
  128. // Returns HXR_OK if resolved time is returned in lEffectiveResolveTime,
  129. // else returns HXR_FAILED.
  130. HX_RESULT
  131. SmilTimeValue::getEffectiveResolvedTime(REF(INT32) lEffectiveResolvedTime)
  132. {
  133.     HX_RESULT retval = HXR_OK;
  134.     lEffectiveResolvedTime = SMILTIME_NEGATIVE_INFINITY;
  135.     switch (m_type)
  136.     {
  137. case SmilTimeSyncBase:
  138. #if defined(ENABLE_SYNC_TO_PREV)
  139. case SmilTimeSyncToPrev:
  140. #endif
  141. case SmilTimeMediaMarker:
  142. case SmilTimeEvent:
  143. {
  144.     if (isTimeResolved())
  145.     {
  146. // /EH- the following should *always* be true:
  147. HX_ASSERT(m_lResolvedToTime >= m_lWhenTimeWasResolved);
  148. // /Note: resolvedToTime doesn't include offset:
  149. lEffectiveResolvedTime = m_lResolvedToTime;
  150. #define XXXEH_OFFSET_NOT_ALREADY_ACCOUNTED_FOR
  151. #if defined(XXXEH_OFFSET_NOT_ALREADY_ACCOUNTED_FOR)
  152. if (SmilTimeEvent == m_type
  153. // /XXXEH- TODO: handle SmilTimeMediaMarker here, too,
  154. // if and when we get internal markers (event-like
  155. // ones) working:
  156. ||  (isSyncBaseTimeVal()  &&  m_bTreatSyncArcAsEvent))
  157. {
  158.     INT32 lEffectiveOffset = m_lOffset;
  159.     if (lEffectiveOffset < 0)
  160.     {
  161. lEffectiveOffset = m_lWhenTimeWasResolved -
  162. m_lResolvedToTime;
  163. if (lEffectiveOffset < m_lOffset)
  164. {
  165.     // /Resolved-at time was well before resolved-to
  166.     // time minus |offset|, so the entire offset is
  167.     // used:
  168.     lEffectiveOffset = m_lOffset;
  169. }
  170.     }
  171.     lEffectiveResolvedTime += lEffectiveOffset;
  172. }
  173. #endif
  174.     }
  175.     else
  176.     {
  177. retval = HXR_FAILED;
  178.     }
  179. }
  180. break;
  181. // /XXXEH- TODO: figure out how to handle wallclock; I think
  182. // it should just work the same as clock values:
  183. case SmilTimeWallclock:
  184. case SmilTimeClockValue:
  185. case SmilTimeOffset:
  186. {
  187.     if (isTimeResolved())
  188.     {
  189. lEffectiveResolvedTime = m_lOffset;
  190.     }
  191.     else
  192.     {
  193. retval = HXR_FAILED;
  194. // /All wallclock, clock, and offset values should have
  195. // been set as resolved at parse time:
  196. HX_ASSERT(isTimeResolved());
  197.     }
  198. }
  199. break;
  200. default:
  201. {
  202.     retval = HXR_FAILED;
  203. }
  204. break;
  205.     }
  206.     return retval;
  207. }
  208. HX_RESULT
  209. SmilTimeValue::parseValue(const char* pPos,
  210.   SMILSyncAttributeTag nTag,
  211.   // /Needed for self-references:
  212.   const char* pThisElementID)
  213. {
  214.     HX_RESULT ret = HXR_OK;
  215.     if (pPos == (const char*)NULL)
  216.     {
  217. ret = HXR_FAIL;
  218.     }
  219.     else if (*pPos == '+' || *pPos == '-')
  220.     {
  221. HX_ASSERT(nTag == SMILSyncAttrBegin);
  222. if (nTag == SMILSyncAttrBegin)
  223. {
  224.     ret = parseOffset(pPos);
  225.     m_type = SmilTimeOffset;
  226.     if (SUCCEEDED(ret))
  227.     {
  228. m_bTimeIsResolved = TRUE;
  229.     }
  230. }
  231. else
  232. {
  233.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  234.     errHandler.ReportError(SMILErrorBadTimeValue, pPos, 
  235. m_ulStartLine);
  236.     return ret;
  237. }
  238.     }
  239.     else if (isdigit(*pPos)
  240. // /Fixes PR 42592:
  241. // "0.5s" was OK but ".5s" was being treated as unresolved:
  242. ||  '.' == *pPos)
  243.     {
  244. ret = parseOffset(pPos);
  245. if (SUCCEEDED(ret))
  246. {
  247.     m_bTimeIsResolved = TRUE;
  248. }
  249. // this is actually a Clock Value if it is an end
  250. // time.
  251. if (nTag == SMILSyncAttrBegin)
  252. {
  253.     m_type = SmilTimeOffset;
  254. }
  255. else // nTag == SMILSyncAttrEnd
  256. {
  257.     m_type = SmilTimeClockValue;
  258. }
  259.     }
  260. #if defined(ENABLE_SYNC_TO_PREV)
  261.     else if (strncmp(pPos, "prev", 4) == 0)
  262.     {
  263. // syncToPrev-value
  264. ret = parseSyncToPrev(pPos);
  265.     }
  266. #endif
  267.     else if (strncmp(pPos, "wallclock", 9) == 0)
  268.     {
  269. // wallclock-sync-value
  270. ret = parseWallClockValue(pPos);
  271.     }
  272.     else
  273.     {
  274. const char* pDotPos = NULL;
  275. BOOL bEscape = FALSE;
  276. UINT32 len = strlen(pPos);
  277. char* idref = new char [len+1];
  278. char* idrefPos = idref;
  279. *idrefPos = '';
  280. char* command = new char [len+1];
  281. char* commandPos = command;
  282. *commandPos = '';
  283. const char* pOffset = NULL;
  284. enum { IDREF, ESCAPE, COMMAND, END, OFFSET } state = IDREF;
  285. const char* pBegin = pPos;
  286. while (*pPos)
  287. {
  288.     switch (state)
  289.     {
  290.     case ESCAPE:
  291. *idrefPos++ = *pPos;
  292. state = IDREF;
  293. break;
  294.     case IDREF:
  295. if (*pPos == '\')
  296. {
  297.     // /Don't include escape char in idref; go to next char:
  298.     state = ESCAPE;
  299. }
  300. else if (*pPos == '.')
  301. {
  302.     *idrefPos = '';
  303.     state = COMMAND;
  304. }
  305. else if (isspace(*pPos))
  306. {
  307.     *idrefPos = '';
  308.     state = END;
  309. }
  310. else if (*pPos == '+' || *pPos == '-')
  311. {
  312.     *idrefPos++ = '';
  313.     pOffset = pPos;
  314.     state = OFFSET;
  315. }
  316. else
  317. {
  318.     *idrefPos++ = *pPos;
  319. }
  320. break;
  321.     case COMMAND:
  322.         if (isspace(*pPos))
  323. {
  324.     *commandPos = '';
  325.     state = END;
  326. }
  327. else if (*pPos == '+' || *pPos == '-')
  328. {
  329.     pOffset = pPos;
  330.     *commandPos = '';
  331.     state = OFFSET;
  332. }
  333. else
  334. {
  335.     *commandPos++ = *pPos;
  336. }
  337. break;
  338.     case END:
  339. if (*pPos == '+' || *pPos == '-')
  340. {
  341.     pOffset = pPos;
  342.     state = OFFSET;
  343. }
  344. break;
  345.     case OFFSET:
  346. break;
  347.     }
  348.     ++pPos;
  349. }
  350. if (state == COMMAND)
  351. {
  352.     *commandPos = '';
  353. }
  354. else if (state == IDREF || state == ESCAPE)
  355. {
  356.     *idrefPos = '';
  357. }
  358.         // XXXMEH - if this is an animation element, then we
  359.         // will handle the ".repeat(x)" syntax differently than
  360.         // we treat sources. We will treat ".repeat(x)" as an
  361.         // event rather than a sync-arc.
  362.         BOOL bIsAnimate = FALSE;
  363.         if (m_pElement && m_pElement->m_pNode &&
  364.             (m_pElement->m_pNode->m_tag == SMILAnimate       ||
  365.              m_pElement->m_pNode->m_tag == SMILSet           ||
  366.              m_pElement->m_pNode->m_tag == SMILAnimateMotion ||
  367.              m_pElement->m_pNode->m_tag == SMILAnimateColor))
  368.         {
  369.             bIsAnimate = TRUE;
  370.         }
  371. if (*command == '')
  372. {
  373.     // /The SMIL Boston draft supports the fact that the name of the
  374.     // event ("Event-symbol") is required and is what is used when
  375.     // no "Eventbase-element." precedes it.  Thus, we need to
  376.     // treat the idref as the command string and use this 
  377.     // element's id for the idref:
  378.     // /HOWEVER, for PR 69849 (needed for PR 58290) fix, if event is
  379.     // "accesskey(...)", then the event is not self-generated and is
  380.     // not raised for another element, so give it a fake id here so
  381.     // special-case code isn't needed in multiple places, elsewhere:
  382.     if (!strncmp(idref, "accesskey(", 10))
  383.     {
  384. ret = parseEvent(
  385. // /Use this string (an invalid XML id) as the fake ID:
  386. ACCESSKEY_EVENT_FAKE_ID_STRING, // /fake ID.
  387. idref, // /<==actually the command (i.e., Event-symbol)
  388. pOffset);
  389.     }
  390.     else
  391.     {
  392. ret = parseEvent(pThisElementID,
  393. idref, // /<==actually the command (i.e., Event-symbol)
  394. pOffset);
  395.     }
  396. }
  397. else if (strcmp(command, "begin") == 0 ||
  398. #if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
  399. #else
  400. ((0 == strncmp(command, "repeat(", 7)) && !bIsAnimate)  ||
  401. #endif
  402.  strcmp(command, "end") == 0)
  403. {
  404. // base, memeber, offset
  405.     ret = parseSyncBase(idref, command, pOffset);
  406. }
  407. else if (strncmp(command, "marker(", 7) == 0)
  408. {
  409.     ret = parseMarker(idref, command, pOffset);
  410. }
  411. else // /everything else is an event (i.e., "Event-symbol") name:
  412. {
  413.     ret = parseEvent(idref, command, pOffset);
  414. }
  415. HX_VECTOR_DELETE(command);
  416. HX_VECTOR_DELETE(idref);
  417.     }
  418.     // /We need to make sure we set scheduled time values' resolved-to times
  419.     // in case these times are used AFTER the element has already begun
  420.     // playing or finished playing:
  421.     if (SmilTimeOffset == m_type   || 
  422. SmilTimeClockValue == m_type  ||
  423. SmilTimeWallclock == m_type)
  424.     {
  425. setResolvedToTime(0);
  426. setWhenTimeWasResolved(0);
  427.     }
  428.     return ret;
  429. }
  430. HX_RESULT
  431. SmilTimeValue::setTimeOffset(time_t tRefTime)
  432. {
  433.     HX_RESULT ret = HXR_OK;
  434.     if (m_type == SmilTimeWallclock)
  435.     {
  436. struct tm ourtime;
  437. ourtime.tm_sec = m_sec; 
  438. ourtime.tm_min = m_min;
  439. ourtime.tm_hour = m_hour;
  440. if (m_day != -1 && m_year != -1 && m_month != -1)
  441. {
  442.     ourtime.tm_mday = m_day;
  443.     // /tm::tm_mon is 0-based, while m_month is 1-based, so we need
  444.     // to subtract 1 (and our parser already made sure m_month is
  445.     // greater than 0 and less than 13):
  446.     ourtime.tm_mon = m_month - 1;
  447.     ourtime.tm_year = m_year - 1900;
  448. }
  449. else
  450. {
  451.     time_t thetime;
  452.     time(&thetime);
  453.     struct tm* cur;
  454.     cur = localtime(&thetime);
  455.     ourtime.tm_mday = cur->tm_mday;
  456.     ourtime.tm_mon = cur->tm_mon;
  457.     ourtime.tm_year = cur->tm_year;
  458.     ourtime.tm_isdst = cur->tm_isdst;
  459. }
  460. time_t thisTime = mktime(&ourtime);
  461. double diff = 0.0;
  462. if (m_bRelativeToUTC)
  463. {
  464. //XXXJHUG need a crossplatform way to get the timezone offset.
  465. #ifdef _WIN32
  466.     diff = difftime(thisTime + _timezone, tRefTime + m_UTCOffsetMin);
  467. #else
  468.     diff = difftime(thisTime, tRefTime + m_UTCOffsetMin);
  469. #endif
  470. }
  471. else
  472. {
  473.     diff = difftime(thisTime, tRefTime);
  474. }
  475.         double dDiffMS  = diff * 1000.0;
  476.         double dMaxDiff = (double) 0x7FFFFFFF;
  477.         double dMinDiff = -dMaxDiff; 
  478.         // Clip at the min and max 
  479.         if (dDiffMS > dMaxDiff)
  480.         {
  481.             dDiffMS = dMaxDiff - 10;
  482.         }
  483.         else if (dDiffMS < dMinDiff)
  484.         {
  485.             dDiffMS = dMinDiff +10;
  486.         }
  487.         // Now convert to INT32
  488.         m_lOffset = (INT32) dDiffMS;
  489. m_lOriginalOffset = m_lOffset;
  490.     }
  491.     return ret;
  492. }
  493. HX_RESULT
  494. SmilTimeValue::parseOffset(const char* pCh)
  495. {
  496.     HX_RESULT pnretval = HXR_OK;
  497.     // eat whitespace
  498.     while (*pCh && isspace(*pCh))
  499.     {
  500. ++pCh;
  501.     }
  502.     if (*pCh == '-')
  503.     {
  504. // /Eat any whitespace following the '-'
  505. do
  506. {
  507.     ++pCh;
  508. } while (*pCh  &&  isspace(*pCh));
  509. UINT32 clockTime = 0;
  510. pnretval = parseClockValue(pCh, clockTime);
  511. m_lOffset = -(INT32)clockTime;
  512.     }
  513.     else if (*pCh == '+')
  514.     {
  515. // /Eat any whitespace following the '+'
  516. do
  517. {
  518.     ++pCh;
  519. } while (*pCh  &&  isspace(*pCh));
  520. UINT32 clockTime = 0;
  521. pnretval = parseClockValue(pCh, clockTime);
  522. m_lOffset = (INT32)clockTime;
  523.     }
  524.     else
  525.     {
  526. UINT32 clockTime = 0;
  527. pnretval = parseClockValue(pCh, clockTime);
  528. m_lOffset = (INT32)clockTime;
  529.     }
  530.     m_lOriginalOffset = m_lOffset;
  531.     return pnretval;
  532. }
  533. HX_RESULT
  534. SmilTimeValue::parseClockValue(const char* pValue, 
  535.        UINT32& ulTimeValue)
  536. {
  537.     if (!pValue  ||  strlen(pValue) < 1)
  538.     {
  539. return HXR_FAILED;
  540.     }
  541.     // try npt
  542.     char* pPtr = (char *)strstr(pValue, "npt=");
  543.     if(pPtr)
  544.     {
  545. pPtr += 4;  // point to beginning of clock value
  546. NPTime clockTime(pPtr);
  547. ulTimeValue = (UINT32)clockTime;
  548. return HXR_OK;
  549.     }
  550.     // try smpte
  551.     pPtr = (char *)strstr(pValue, "smpte=");
  552.     if(pPtr)
  553.     {
  554. pPtr += 6;  // point to beginning of clock value
  555. SMPTETimeCode clockTime(pPtr);
  556. ulTimeValue = (UINT32)clockTime;
  557. return HXR_OK;
  558.     }
  559.     pPtr = (char *)strstr(pValue, "smpte-30-drop=");
  560.     if(pPtr)
  561.     {
  562. pPtr += 14;  // point to beginning of clock value
  563. SMPTETimeCode clockTime(pPtr);
  564. ulTimeValue = (UINT32)clockTime;
  565. return HXR_OK;
  566.     }
  567.     pPtr = (char *)strstr(pValue, "smpte-25=");
  568.     if(pPtr)
  569.     {
  570. pPtr += 9;  // point to beginning of clock value
  571. SMPTETimeCode clockTime;
  572.         clockTime.m_framesPerSec = SMPTETimeCode::FPS_25;
  573.         clockTime.fromString(pPtr);
  574. ulTimeValue = (UINT32)clockTime;
  575. return HXR_OK;
  576.     }
  577.     else
  578.     {
  579. BOOL bAllow_h_min_s_ms_units = TRUE;
  580. BOOL bSucceeded = FALSE;
  581. // /First, get rid of trailing spaces:
  582. UINT32 ulStrlen = (UINT32)strlen(pValue);
  583. char* pEnd = (char*)(&pValue[ulStrlen-1]);
  584. while (isspace(*pEnd)  &&  pEnd>pValue)
  585. {
  586.     pEnd--;
  587. }
  588. pEnd[1] = '';
  589. // /This first tries just hh:mm:ss with no prefix/suffix
  590. // and then tries suffixes: {"h" | "min" | "s" | "ms"} with
  591. // the default (no ":" inside and no prefix or suffix) being
  592. // in seconds per the SMIL 1.0 spec ([SMIL 1.0 compliance]
  593. // Fixes PR 22673):
  594. NPTime clockTime(pValue, bAllow_h_min_s_ms_units, bSucceeded);
  595. if (bSucceeded)
  596. {
  597.     ulTimeValue = (UINT32)clockTime;
  598.     return HXR_OK;
  599. }
  600.     }
  601.     return HXR_FAIL;
  602. }
  603. HX_RESULT
  604. SmilTimeValue::parseEvent(const char* pBase, const char* pEvent, 
  605.   const char* pOffset)
  606. {
  607.     HX_RESULT rslt = HXR_OK;
  608.     m_type = SmilTimeEvent;
  609.     UINT32 ulLen = 0;
  610.     if (pBase)
  611.     {
  612. ulLen = strlen(pBase);
  613. m_idRef = pBase;
  614.     }
  615.     
  616.     if( !pEvent  ||  !strlen(pEvent))
  617.     {
  618. // /XXXEH- not sure why we'd ever get this state so put assert here
  619. // to check it out:
  620. HX_ASSERT(pEvent  &&  strlen(pEvent));
  621. m_pEventName = NULL;
  622. rslt = HXR_UNEXPECTED; // /XXXEH- at least I *think* it's unexpected.
  623.     }
  624.     else
  625.     {
  626. // /Handle "foo.xyz" as meaning the "xyz" event that may have the
  627. // same name as a sync-arc, e.g., "foo.begin".  Treat them as
  628. // events that get resolved when the m_idRef element (renderer)
  629. // fires off a an event with the matching name:
  630. if ('\' == *pEvent  &&  strlen(pEvent)>=2)
  631. {
  632.     // /Add -1 for removing the  '', +1 for the terminating '':
  633.     m_pEventName = new char[strlen(pEvent)-1 + 1];
  634.     if (m_pEventName)
  635.     {
  636. strcpy(m_pEventName, &pEvent[1]); /* Flawfinder: ignore */
  637.     }
  638.     else
  639.     {
  640. rslt = HXR_OUTOFMEMORY;
  641.     }
  642. }
  643. else
  644. {
  645.     m_pEventName = new char[strlen(pEvent)+1];
  646.     if (m_pEventName)
  647.     {
  648. strcpy(m_pEventName, pEvent); /* Flawfinder: ignore */
  649.     }
  650.     else
  651.     {
  652. rslt = HXR_OUTOFMEMORY;
  653.     }
  654. }
  655.     }
  656.     if (SUCCEEDED(rslt)  &&  pOffset && *pOffset)
  657.     {
  658. parseOffset(pOffset);
  659.     }
  660.     return rslt;
  661. }
  662. HX_RESULT
  663. SmilTimeValue::parseSyncBase(const char* pBase, const char* pCommand, 
  664.      const char* pOffset)
  665. {
  666.     m_type = SmilTimeSyncBase;
  667.     UINT32 ulLen = strlen(pBase);
  668.     if (pBase  &&  pCommand)
  669.     {
  670. m_idRef = pBase;
  671.     }
  672.     else
  673.     {
  674. HX_ASSERT(FALSE);
  675. return HXR_FAIL;
  676.     }
  677.     BOOL bTimeValueOK = FALSE;
  678.     BOOL bRepeatValueParsed = FALSE;
  679.     if (strncmp(pCommand, "begin", 5) == 0)
  680.     {
  681. m_position = SMILEventSourceBegin;
  682. bTimeValueOK = TRUE;
  683.     }
  684.     else if (strncmp(pCommand, "end", 3) == 0)
  685.     {
  686. m_position = SMILEventSourceEnd;
  687. bTimeValueOK = TRUE;
  688.     }
  689. #if defined(XXXEH_REPEAT_VALUE_TIMING_SHOULD_BE_EVENT_BASED)
  690. #else
  691.     else if (strncmp(pCommand, "repeat(", 7) == 0)
  692.     {
  693. bRepeatValueParsed = TRUE;
  694. INT32 strlenCommand = strlen(pCommand);
  695. if (strlenCommand >= 9  &&  ')' == pCommand[strlenCommand-1])
  696. {
  697.     m_position = SMILEventSourceBegin;
  698.     char* pTmp = (char*)&pCommand[7];
  699.     // /Make sure that every character inside the () is a number:
  700.     while (*pTmp  &&  ')' != *pTmp  &&  '0'<=*pTmp  &&  '9'>=*pTmp)
  701.     {
  702. pTmp++;
  703.     }
  704.     if (pTmp == (char*)&pCommand[strlenCommand-1])
  705.     {
  706. INT32 lNum = (INT32)atoi(&pCommand[7]);
  707. // /0 or negative repeat iterations are not allowed, even
  708. // though repeat(0) *could* have been interpreted as the
  709. // first play of foo (prior to it repeating), but wasn't:
  710. if (lNum > 0)
  711. {
  712.     *pTmp = '';
  713.     m_idRef += "_repeat_copy_";
  714.     m_idRef += &pCommand[7];
  715.     *pTmp = ')'; // /restore it.
  716.     m_uRepeatIteration = (UINT16)lNum;
  717.     bTimeValueOK = TRUE;
  718. }
  719.     }
  720. }
  721.     }
  722. #endif
  723.     if (!bTimeValueOK)
  724.     {
  725. if (!bRepeatValueParsed)
  726. {
  727.     HX_ASSERT(FALSE);
  728. }
  729. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  730. errHandler.ReportError(SMILErrorBadTimeValue, pCommand, 
  731.     m_ulStartLine);
  732. return HXR_FAIL;
  733.     }
  734.     if (pOffset)
  735.     {
  736. parseOffset(pOffset);
  737.     }
  738.     return HXR_OK;
  739. }
  740. HX_RESULT SmilTimeValue::parseMarker(const char* pBase, const char* pMarker, const char* pOffset)
  741. {
  742.     HX_RESULT retVal = HXR_FAIL;
  743.     if (pBase && pMarker)
  744.     {
  745.         // Set the type
  746.         m_type = SmilTimeMediaMarker;
  747.         // Set the base
  748.         m_idRef = pBase;
  749.         // Set the offset (if we have one)
  750.         if (pOffset)
  751.         {
  752.             parseOffset(pOffset);
  753.         }
  754.         // Move past the "marker.(", which we already
  755.         // checked for before we were called
  756.         pMarker += 7;
  757.         // Allocate space for our string
  758.         HX_VECTOR_DELETE(m_pszMarkerName);
  759.         m_pszMarkerName = new char [strlen(pMarker) + 1];
  760.         if (m_pszMarkerName)
  761.         {
  762.             // Look for the end of the marker name
  763.             char* pEnd = (char *)strchr(pMarker, ')');
  764.             if (pEnd)
  765.             {
  766.                 // Copy the full marker name - might or
  767.                 // might not contain an external file reference
  768.                 strncpy(m_pszMarkerName, pMarker, pEnd - pMarker); /* Flawfinder: ignore */
  769.                 m_pszMarkerName[pEnd - pMarker] = '';
  770.                 // Now parse to see if there is an external file reference
  771.                 CHXString cMarker;
  772.                 CHXString cExtFileName;
  773.                 BOOL      bIsExternalMarker = m_bIsExternalMarker;
  774.                 retVal = CSmilParser::parseMarkerURI(m_pszMarkerName,
  775.                                                      cMarker,
  776.                                                      bIsExternalMarker,
  777.                                                      cExtFileName);
  778.                 m_bIsExternalMarker = bIsExternalMarker;
  779.                 if (SUCCEEDED(retVal) && m_bIsExternalMarker)
  780.                 {
  781.                     // Set the flag in the element that this
  782.                     // element references an external media marker file
  783.                     m_pElement->m_bUsesExternalMediaMarkerFile = TRUE;
  784.                     // We just need to copy the marker string and
  785.                     // the external file name string into our members
  786.                     HX_VECTOR_DELETE(m_pszExternalMarkerFileName);
  787.                     m_pszExternalMarkerFileName = new char [cExtFileName.GetLength() + 1];
  788.                     if (m_pszExternalMarkerFileName)
  789.                     {
  790.                         strcpy(m_pszExternalMarkerFileName, (const char*) cExtFileName); /* Flawfinder: ignore */
  791.                         HX_VECTOR_DELETE(m_pszExternalMarkerName);
  792.                         m_pszExternalMarkerName = new char [cMarker.GetLength() + 1];
  793.                         if (m_pszExternalMarkerName)
  794.                         {
  795.                             strcpy(m_pszExternalMarkerName, (const char*) cMarker); /* Flawfinder: ignore */
  796.                         }
  797.                         else
  798.                         {
  799.                             retVal = HXR_OUTOFMEMORY;
  800.                         }
  801.                     }
  802.                     else
  803.                     {
  804.                         retVal = HXR_OUTOFMEMORY;
  805.                     }
  806.                 }
  807.             }
  808.         }
  809.     }
  810.     if (FAILED(retVal))
  811.     {
  812. HX_ASSERT(FALSE);
  813. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  814. errHandler.ReportError(SMILErrorBadTimeValue, pMarker, m_ulStartLine);
  815.     }
  816.     return retVal;
  817. }
  818. #if defined(ENABLE_SYNC_TO_PREV)
  819. HX_RESULT
  820. SmilTimeValue::parseSyncToPrev(REF(const char*) pCh)
  821. {
  822.     HX_RESULT ret = HXR_OK;
  823.     // move past "prev."
  824.     pCh += 5;
  825.     m_type = SmilTimeSyncToPrev;
  826.     if (strncmp(pCh, "begin", 5) == 0)
  827.     {
  828. m_position = SMILEventSourceBegin;
  829. pCh += 5;
  830.     }
  831.     else if (strncmp(pCh, "end", 3) == 0)
  832.     {
  833. m_position = SMILEventSourceEnd;
  834. pCh += 3;
  835.     }
  836.     else
  837.     {
  838. HX_ASSERT(FALSE);
  839. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  840. errHandler.ReportError(SMILErrorBadTimeValue, pCh, 
  841.     m_ulStartLine);
  842. return HXR_FAIL;
  843.     }
  844.     // eat white space
  845.     while (*pCh && isspace(*pCh))
  846.     {
  847. ++pCh;
  848.     }
  849.     if (*pCh == '+' || *pCh == '-')
  850.     {
  851. ret = parseOffset(pCh);
  852.     }
  853.     
  854.     return ret;
  855. }
  856. #endif
  857. HX_RESULT
  858. SmilTimeValue::parseWallClockValue(REF(const char*) pCh)
  859. {
  860.     HX_RESULT ret = HXR_OK;
  861.     m_type = SmilTimeWallclock;
  862.     m_bTimeIsResolved = TRUE;
  863.     // move past "wallclock("
  864.     pCh += 10;
  865.     // eat whitespace.
  866.     while (*pCh && isspace(*pCh))
  867.     {
  868. ++pCh;
  869.     }
  870.     // find the end ')'
  871.     const char* begin = pCh;
  872.     const char* end = NULL;
  873.     const char* pT = NULL;
  874.     const char* pTimeZone = NULL;
  875.     const char* pTimePos = NULL;
  876.     const char* pDatePos = NULL;
  877.     INT32 year = -1;
  878.     INT32 month = -1;
  879.     INT32 day = -1;
  880.     INT32 hour = 0;
  881.     INT32 min = 0;
  882.     INT32 sec = 0;
  883.     INT32 ms = 0;
  884.     char buf[10]; /* Flawfinder: ignore */
  885.     
  886.     // store offset in min.
  887.     INT32 UTCOffset = 0;
  888.     while (*pCh)
  889.     {
  890. if (*pCh == ')')
  891. {
  892.     end = pCh;
  893. }
  894. else if (*pCh == 'T')
  895. {
  896.     pT = pCh;
  897. }
  898. else if (isspace(*pCh) || *pCh == '+' || *pCh == '-' || *pCh == 'Z')
  899. {
  900.     // this will find the last +, - or Z... which is what we want.
  901.     pTimeZone = pCh;
  902. }
  903. else if (!isdigit(*pCh) && *pCh != ':' && *pCh != '-' && *pCh != '.')
  904. {
  905.     ret = HXR_FAIL;
  906. }
  907. ++pCh;
  908.     }
  909.     if (FAILED(ret))
  910.     {
  911. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  912. errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  913.     m_ulStartLine);
  914. goto cleanup;
  915.     }
  916.     // check for a 'T'
  917.     if (pT)
  918.     {
  919. //YYYY-MM-DDT
  920. if (*(begin+4) == '-' && *(begin+7) == '-' && pT == (begin+10))
  921. {
  922.     pDatePos = begin;
  923.     if (pTimeZone < begin+10)
  924.     {
  925. pTimeZone = NULL;
  926.     }
  927. }
  928. else
  929. {
  930.     ret = HXR_FAIL;
  931.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  932.     errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  933. m_ulStartLine);
  934.     goto cleanup;
  935. }
  936. if (*(pT+3) == ':')
  937. {
  938.     pTimePos = pT+1;
  939. }
  940. else
  941. {
  942.     ret = HXR_FAIL;
  943.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  944.     errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  945. m_ulStartLine);
  946.     goto cleanup;
  947. }
  948.     }
  949.     // else just the date or time.
  950.     //YYYY-MM-DDT
  951.     else if (*(begin+4) == '-' && *(begin+7) == '-' && pT == (begin+10))
  952.     {
  953. // just date
  954. // there is a date.
  955. pDatePos = begin;
  956. if (pTimeZone < begin+10)
  957. {
  958.     pTimeZone = NULL;
  959. }
  960.     }
  961.     else if (*(begin+2) == ':')
  962.     {
  963. pTimePos = begin;
  964.     }
  965.     else
  966.     {
  967. ret = HXR_FAIL;
  968. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  969. errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  970.     m_ulStartLine);
  971. goto cleanup;
  972.     }
  973.     // there is a date.
  974.     if (pDatePos)
  975.     {
  976. //YYYY-MM-DDT
  977. const char* pos = pDatePos;
  978. strncpy(buf, pos, 4); /* Flawfinder: ignore */
  979. buf[4] = '';
  980. pos += 5;
  981. year = HX_SAFEINT(strtol(buf, 0, 10));
  982. if (year < 0 || year > 9999)
  983. {
  984.     ret = HXR_FAIL;
  985.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  986.     errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos, 
  987. m_ulStartLine);
  988.     goto cleanup;
  989. }
  990. strncpy(buf, pos, 2); /* Flawfinder: ignore */
  991. buf[2] = '';
  992. pos += 3;
  993. month = HX_SAFEINT(strtol(buf, 0, 10));
  994. // /month can't be 0 or less or greater than 12 (i.e., it's
  995. // 1-based):
  996. if (month < 1 || month > 12)
  997. {
  998.     ret = HXR_FAIL;
  999.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1000.     errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos, 
  1001. m_ulStartLine);
  1002.     goto cleanup;
  1003. }
  1004. strncpy(buf, pos, 2); /* Flawfinder: ignore */
  1005. buf[2] = '';
  1006. pos += 3;
  1007. day = HX_SAFEINT(strtol(buf, 0, 10));
  1008. if (day < 0 || day > 31)
  1009. {
  1010.     ret = HXR_FAIL;
  1011.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1012.     errHandler.ReportError(SMILErrorBadWallClockValue, pDatePos, 
  1013. m_ulStartLine);
  1014.     goto cleanup;
  1015. }
  1016.     }
  1017.     if (pTimePos)
  1018.     {
  1019.     //HH:MM...
  1020. const char* pos = pTimePos;
  1021. strncpy(buf, pos, 2); /* Flawfinder: ignore */
  1022. buf[2] = '';
  1023. pos += 3;
  1024. hour = HX_SAFEINT(strtol(buf, 0, 10));
  1025. if (hour < 0 || hour > 24)
  1026. {
  1027.     ret = HXR_FAIL;
  1028.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1029.     errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos, 
  1030. m_ulStartLine);
  1031.     goto cleanup;
  1032. }
  1033. // just time
  1034. strncpy(buf, pos, 2); /* Flawfinder: ignore */
  1035. buf[2] = '';
  1036. pos += 3;
  1037. min = HX_SAFEINT(strtol(buf, 0, 10));
  1038. if (min < 0 || min > 59)
  1039. {
  1040.     ret = HXR_FAIL;
  1041.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1042.     errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos, 
  1043. m_ulStartLine);
  1044.     goto cleanup;
  1045. }
  1046. if (*(pos-1) == ':')
  1047. {
  1048.     strncpy(buf, pos, 2); /* Flawfinder: ignore */
  1049.     buf[2] = '';
  1050.     pos +=3;
  1051.     sec = HX_SAFEINT(strtol(buf, 0, 10));
  1052.     if (sec < 0 || sec > 59)
  1053.     {
  1054. ret = HXR_FAIL;
  1055. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1056. errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos, 
  1057.     m_ulStartLine);
  1058. goto cleanup;
  1059.     }
  1060.     if (*(pos-1) == '.')
  1061.     {
  1062. // find end.
  1063. UINT32 len = 0;
  1064. if (pTimeZone)
  1065. {
  1066.     len = pTimeZone - pos;
  1067. }
  1068. else
  1069. {
  1070.     len = end - pos;
  1071. }
  1072. strncpy(buf, pos, len); /* Flawfinder: ignore */
  1073. buf[len] = '';
  1074. pos += len;
  1075. if (*buf)
  1076. {
  1077.     if (isdigit(*buf))
  1078.     {
  1079. ms = (*buf - '0') * 100;
  1080. if (isdigit(*(buf+1)))
  1081. {
  1082.     ms += (*buf - '0') * 10;
  1083.     if (isdigit(*(buf+2)))
  1084.     {
  1085. ms += (*buf - '0');
  1086.     }
  1087. }
  1088.     }
  1089.     else
  1090.     {
  1091. ret = HXR_FAIL;
  1092. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1093. errHandler.ReportError(SMILErrorBadWallClockValue, pTimePos, 
  1094.     m_ulStartLine);
  1095. goto cleanup;
  1096.     }
  1097. }
  1098.     }
  1099. }
  1100.     }
  1101.     if (pTimeZone)
  1102.     {
  1103. BOOL bSyntaxOK = FALSE;
  1104. const char* begin = pTimeZone;
  1105. if (*pTimeZone == 'Z')
  1106. {
  1107.     m_bRelativeToUTC = TRUE;
  1108.     UTCOffset = 0;
  1109.     bSyntaxOK = TRUE;
  1110. }
  1111. else if ((*pTimeZone == '+' || *pTimeZone == '-') && *(pTimeZone+3) == ':')
  1112. {
  1113.     m_bRelativeToUTC = TRUE;
  1114.     int sign = 1;
  1115.     if (*pTimeZone == '-')
  1116.     {
  1117. ++pTimeZone;
  1118. sign = -1;
  1119.     }
  1120.     else if (*pTimeZone == '+')
  1121.     {
  1122. ++pTimeZone;
  1123.     }
  1124.     strncpy(buf, pTimeZone, 2); /* Flawfinder: ignore */
  1125.     buf[2] = '';
  1126.     pTimeZone += 3;
  1127.     INT32 hour = HX_SAFEINT(strtol(buf, 0, 10));
  1128.     if (hour < 0 || hour > 12)
  1129.     {
  1130. ret = HXR_FAIL;
  1131. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1132. errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  1133.     m_ulStartLine);
  1134. goto cleanup;
  1135.     }
  1136.     UTCOffset = hour * 60;
  1137.     strncpy(buf, pTimeZone, 2); /* Flawfinder: ignore */
  1138.     buf[2] = '';
  1139.     pTimeZone += 3;
  1140.     INT32 min = HX_SAFEINT(strtol(buf, 0, 10));
  1141.     if (min < 0 || min > 59)
  1142.     {
  1143. ret = HXR_FAIL;
  1144. CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1145. errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  1146.     m_ulStartLine);
  1147. goto cleanup;
  1148.     }
  1149.     UTCOffset += min;
  1150.     UTCOffset *= sign;
  1151.     bSyntaxOK = TRUE;
  1152. }
  1153. else if (isspace(*pTimeZone))
  1154. {
  1155.     bSyntaxOK = TRUE;
  1156.     do
  1157.     {
  1158. *pTimeZone++;
  1159. if (!(*pTimeZone)  ||  ')' == *pTimeZone)
  1160. {
  1161.     break;
  1162. }
  1163. if (!isspace(*pTimeZone))
  1164. {
  1165.     bSyntaxOK = FALSE;
  1166.     break;
  1167. }
  1168.     } while (*pTimeZone);
  1169. }
  1170. if (!bSyntaxOK)
  1171. {
  1172.     ret = HXR_FAIL;
  1173.     CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
  1174.     errHandler.ReportError(SMILErrorBadWallClockValue, begin, 
  1175. m_ulStartLine);
  1176.     goto cleanup;
  1177. }
  1178.     }
  1179.     // else use the -1 value.
  1180.     m_UTCOffsetMin = (INT16)UTCOffset;
  1181.     m_ms = (UINT16)ms;
  1182.     m_sec = (UINT8)sec;
  1183.     m_min = (UINT8)min;
  1184.     m_hour = (UINT8)hour;
  1185.     m_day = (INT8)day;
  1186.     m_month = (INT8)month;
  1187.     m_year = (INT16)year;
  1188. cleanup:
  1189.     if (SUCCEEDED(ret))
  1190.     {
  1191. m_bTimeIsResolved = TRUE;
  1192.     }
  1193.     return ret;
  1194. }
  1195. void SmilTimeValue::setIsTimeResolved(BOOL bIsResolved)
  1196. {
  1197.     m_bTimeIsResolved = bIsResolved;
  1198. }
  1199. HX_RESULT
  1200. SmilTimeValue::setPauseTime(LONG32 lTimeOfPause)
  1201. {
  1202.     HX_RESULT pnr = HXR_OK;
  1203.     if (!isResumeEvent())
  1204.     {
  1205. pnr = HXR_UNEXPECTED;
  1206.     }
  1207.     else
  1208.     {
  1209. m_lTimeOfPause = lTimeOfPause;
  1210.     }
  1211.     return pnr;
  1212. }
  1213. BOOL
  1214. SmilTimeValue::isSameTimeValue(SmilTimeValue* pOtherTimeVal)
  1215. {
  1216.     BOOL bIsSame = FALSE;
  1217.     // /Using this fixes freeze-up in use of strcmp(NULL,...) [PR 65817]
  1218.     // found while fixing Interop Timing #18.37 which has begin="0s;7s" :
  1219.     BOOL bHasSameEventNameOrBothHaveNoEventName = 
  1220.     (NULL == m_pEventName  &&  NULL == pOtherTimeVal->m_pEventName);
  1221.     if (!bHasSameEventNameOrBothHaveNoEventName)
  1222.     {
  1223. if (NULL != m_pEventName  &&  NULL != pOtherTimeVal->m_pEventName)
  1224. {
  1225.     bHasSameEventNameOrBothHaveNoEventName =
  1226.     !strcmp(m_pEventName, pOtherTimeVal->m_pEventName);
  1227. }
  1228.     }
  1229.     // /Now compare type, timing, event name, ...etc:
  1230.     if (pOtherTimeVal == this)
  1231.     {
  1232. bIsSame = TRUE;
  1233.     }
  1234.     else if (pOtherTimeVal  &&
  1235.     m_pElement == pOtherTimeVal->m_pElement  &&
  1236.     m_type == pOtherTimeVal->m_type  &&
  1237.     m_position == pOtherTimeVal->m_position  &&
  1238.     m_uRepeatIteration == pOtherTimeVal->m_uRepeatIteration  &&
  1239.     m_pszMarkerName == pOtherTimeVal->m_pszMarkerName  &&
  1240.     bHasSameEventNameOrBothHaveNoEventName  &&
  1241.     m_lOffset == pOtherTimeVal->m_lOffset  &&
  1242.     m_bTimeIsResolved == pOtherTimeVal->m_bTimeIsResolved)
  1243.     {
  1244. // /Note: if time isn't resolved, we don't care if times are same:
  1245. if (m_bTimeIsResolved  &&
  1246. m_lResolvedToTime  == pOtherTimeVal->m_lResolvedToTime)
  1247. {
  1248.     bIsSame = TRUE;
  1249. }
  1250. else
  1251. {
  1252.     switch (m_type)
  1253.     {
  1254. case SmilTimeOffset:
  1255. case SmilTimeClockValue:
  1256. case SmilTimeWallclock:
  1257. case SmilTimeNone:
  1258. {
  1259.     bIsSame = TRUE;
  1260. }
  1261. break;
  1262. case SmilTimeSyncBase:
  1263. #if defined(ENABLE_SYNC_TO_PREV)
  1264. case SmilTimeSyncToPrev:
  1265. #endif
  1266. case SmilTimeMediaMarker:
  1267. case SmilTimeEvent:
  1268. {
  1269.     HX_ASSERT(m_idRef.GetLength());
  1270.     HX_ASSERT(pOtherTimeVal->m_idRef.GetLength());
  1271.     bIsSame = !strcmp(m_idRef, pOtherTimeVal->m_idRef);
  1272. }
  1273. break;
  1274.     }
  1275. }
  1276.     }
  1277.     return bIsSame;
  1278. }
  1279. BOOL
  1280. SmilTimeValue::deferUntil(LONG32 lNewStartTime)
  1281. {
  1282.     BOOL bSucceeded = FALSE;
  1283.     if (m_bTimeIsResolved  &&  m_lResolvedToTime < lNewStartTime)
  1284.     {
  1285. // /XXXEH- TODO: determine if it's necessary to have a separate
  1286. // variable that keeps track of the deferred amount, and that is
  1287. // reset to 0 if and when this time is used to begin the element.
  1288. // This might be needed if this SmilTimeValue gets reused due to
  1289. // a repeat, seek, or ???
  1290. switch (m_type)
  1291. {
  1292.     case SmilTimeWallclock:
  1293.     case SmilTimeClockValue:
  1294.     case SmilTimeOffset:
  1295.     {
  1296. // /Fixes PR 55936.  Add the amount deferred by to the
  1297. // offset instead of just setting offset to newStartTime:
  1298. m_lOffset += (lNewStartTime - m_lResolvedToTime);
  1299. bSucceeded = TRUE;
  1300.     }
  1301.     break;
  1302.     case SmilTimeSyncBase:
  1303. #if defined(ENABLE_SYNC_TO_PREV)
  1304.     case SmilTimeSyncToPrev:
  1305. #endif
  1306.     case SmilTimeMediaMarker:
  1307.     case SmilTimeEvent:
  1308.     {
  1309. m_lResolvedToTime = lNewStartTime;
  1310. bSucceeded = TRUE;
  1311.     }
  1312.     break;
  1313.     default:
  1314. HX_ASSERT(0);
  1315.     break;
  1316. }
  1317.     }
  1318.     return (bSucceeded);
  1319. }
  1320. void SmilTimeValue::setMarkerTime(UINT32 ulTime)
  1321. {
  1322.     // Only do this if either we aren't resolved
  1323.     if (!m_bTimeIsResolved && m_type == SmilTimeMediaMarker)
  1324.     {
  1325.         // Save our marker time
  1326.         m_ulMarkerTime = ulTime;
  1327.         // This time is an offset from the beginning
  1328.         // of the media. We need to add this offset to
  1329.         // any previously existing offset
  1330.         m_lOffset += (INT32) ulTime;
  1331.         // Convert ourselves to a syncbase and
  1332.         // set the flag which will tell us that
  1333.         // we used to be a media marker.
  1334.         m_type = SmilTimeSyncBase;
  1335.         m_bUsedToBeMediaMarker = TRUE;
  1336.         // By definition we are an offset from the beginning
  1337.         // of the media
  1338.         m_position = SMILEventSourceBegin;
  1339.         // Set the flag saying we are resolved
  1340.         m_bTimeIsResolved = TRUE;
  1341.     }
  1342. }