smlprstime.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:35k
源码类别:

Symbian

开发平台:

C/C++

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