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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: smldoc.cpp,v 1.10.4.8 2004/07/13 22:46:02 ehodge 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. #include <math.h>
  52. #include <ctype.h>  /* for isspace() */
  53. #if defined(_UNIX)  &&  (!(defined(_BEOS)))  &&  defined(USE_XWINDOWS)
  54. #include <X11/Xlib.h>
  55. #include <X11/Xutil.h>
  56. #endif
  57. // include
  58. #include "hxtypes.h"
  59. #include "hxwintyp.h"
  60. #include "hxcom.h"
  61. #include "smiltype.h"
  62. #include "hxcomm.h"
  63. #include "ihxpckts.h"
  64. #include "hxprefs.h"
  65. #include "hxplugn.h"
  66. #include "hxcore.h"
  67. #include "hxwin.h"
  68. #include "hxsite2.h"
  69. #include "hxrendr.h"
  70. #include "hxgroup.h"
  71. #include "hxevent.h"
  72. #include "hxvsurf.h"
  73. #include "hxhyper.h"
  74. #include "hxxml.h"
  75. #include "hxvport.h"
  76. #include "hxfiles.h"
  77. #include "hxausvc.h"
  78. #include "hxclsnk.h"
  79. #if !defined(XXXEH_NEED_TO_ADD_51_PRCNT_OPAQUE_SITE_ON_TOP_TO_DISABLE)
  80. #include "hxvctrl.h"
  81. #endif
  82. #include "hxmmrkr.h"
  83. #include "hxinter.h"
  84. #include "hxupgrd.h"
  85. #include "hxsm2sm.h"
  86. #include "hxerror.h"
  87. // pncont
  88. #include "hxslist.h"
  89. #include "chxpckts.h"
  90. #include "hxstring.h"
  91. #include "hxmap.h"
  92. #include "hxordval.h"
  93. #include "hxstack.h"
  94. #include "rtsputil.h"
  95. // pnmisc
  96. #include "hxurl.h"
  97. #include "hxstrutl.h"
  98. #include "hxwinver.h"
  99. #include "hxtick.h"
  100. #include "dllpath.h"
  101. // rnxmllib
  102. #include "hxxmlprs.h"
  103. // coreres
  104. #include "smilres.h"
  105. // pxcomlib
  106. #include "buffutil.h"
  107. // rmasmil
  108. #include "smlelem.h"
  109. #include "smlparse.h"
  110. #include "smlprstime.h"
  111. #include "smlerror.h"
  112. #include "smlutil.h"
  113. // smlrendr
  114. #include "smlrendr.h"
  115. #include "smlrtype.h"
  116. #include "animattr.h"
  117. #include "animsand.h"
  118. #include "evnthook.h"
  119. #include "siteuser.h"
  120. #include "sitewatc.h"
  121. #include "layout.h"
  122. #include "passivsw.h"
  123. #include "layevent.h"
  124. #include "smcallbk.h"
  125. #include "xdata.h"
  126. #include "smldoc.h"
  127. #if defined(_WINDOWS)
  128. #include "hxalloc.h"
  129. #define IDC_HANDCURSOR 102
  130. #elif defined (_MACINTOSH)
  131. #include "hxmm.h"
  132. #include "cresload.h"
  133. extern FSSpec g_DLLFSpec;
  134. #endif
  135. #if defined(_UNIX)  &&  (!(defined(_BEOS)))  &&  defined(USE_XWINDOWS)
  136. #include <X11/Xlib.h>
  137. #include <X11/Xutil.h>
  138. #include <X11/cursorfont.h>
  139. /* USE_SHM doesn't work yet */
  140. #ifdef USE_SHM
  141. #undef USE_SHM
  142. #endif /* USE_SHM */
  143. #endif
  144. // pndebug
  145. #include "errdbg.h"
  146. #include "debugout.h"
  147. #include "smlrmlog.h"
  148. #include "hxheap.h"
  149. #ifdef _DEBUG
  150. #undef HX_THIS_FILE
  151. static const char HX_THIS_FILE[] = __FILE__;
  152. #endif
  153. #ifdef _WINDOWS
  154. extern HINSTANCE g_hInstance;
  155. #endif
  156. // /This got removed, accidentally, by huge optimization HEAD check-in on
  157. // 11/7/2001, causing show="new" and target="[someLPP]" (launching of LPP)
  158. // to stop working.  Putting this back in fixes PR 69905:
  159. #define XXXEH_USE_OPENWINDOW_METHOD
  160. #define HANDLE_DISCRETE_MEDIA_IN_TrackDurationSet 1
  161. // /XXXEH- talk to core devs; we need them to be able to
  162. // deal with an added track that all of a sudden has its
  163. // duration changed to zero; this seems to work fine for
  164. // tracks that have a zero delay, but subsequent ones
  165. // hang the system when their durations are set to zero:
  166. #define XXXEH_WAITING_FOR_PLAYER_CORE_FIX_FOR_RESETTING_DUR_TO_ZERO
  167. #if defined(XXXEH_WAITING_FOR_PLAYER_CORE_FIX_FOR_RESETTING_DUR_TO_ZERO)
  168. #define ZERO_DUR    1 /* 1 millisecond to trick core. */
  169. #else
  170. #define ZERO_DUR    0
  171. #endif
  172. // /For case where destinationLevel < 10 on a new player and we need to set
  173. // the shared-by-all-players volume to accomodate this, we need to limit it
  174. // for now so source player's volume doesn't cut out:
  175. #define XXXEH_MIN_DEST_AUDIOPLAYER_VOL    10
  176. // /Clamp track soundLevel at some arbitrary, high value; MEH chose 1000% (10x)
  177. // for max-allowed animation of soundLevel; use 1000 until someone complains
  178. // and then ask them what would be better:
  179. #define MAX_ALLOWED_SOUNDLEVEL  1000.0
  180. // /#define XXXEH_DEBUG_HANDLESOURCE_AND_TRACKDURATIONSET
  181. // /#define XXXEH_DEBUGOUT_TRACKSTOPPAUSERESUME
  182. // /#define XXXEH_DEBUGOUT_RESOLVEGROUPDUR
  183. /*
  184.  * CSmilDocumentRenderer methods
  185.  */
  186. CSmilDocumentRenderer::CSmilDocumentRenderer(
  187.     CSmilRenderer* pParent, IUnknown* pContext):
  188.     m_pParent(pParent),
  189.     m_pSmilParser(0),
  190.     m_ulParseResult(HXR_OK),
  191.     m_lRefCount(0),
  192.     m_pRegionMap(0),
  193.     m_pRootLayout(NULL),
  194.     m_pViewportList(NULL),
  195.     m_pRegPointMap(NULL),
  196. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  197.     m_pTransitionMap(0),
  198. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  199.     m_pSiteInfoByRendererMap(0),
  200.     m_pSiteWatcherMap(0),
  201.     m_pGroupInfoMap(0),
  202.     m_pGroupMap(0),
  203.     m_pDeferredSourceMap(0),
  204.     m_pDeferrededRemoveTrackMap(NULL),
  205.     m_bInTrackDurationSetCall(FALSE),
  206.     m_bEventSinkWasSetup(FALSE),
  207.     m_pPausedAndDisabledIDMap(NULL),
  208.     m_pPausedAndDisabledBrightnessMap(NULL),
  209.     m_pPrefetchTrackElementMap(0),
  210.     m_pSiteInfoList(0),
  211.     m_uCurrentGroupIndex(-1),
  212.     m_pPlayToAssocList(0),
  213.     m_pZOrderList(0),
  214.     m_pSiteMgr(0),
  215.     m_pScheduler(0),
  216.     m_pEventList(0),
  217.     m_pFragment(0),
  218.     m_ulCurrentTime(0),
  219.     m_ulEventListPosition(0),
  220.     m_bFirstTimeSync(FALSE),
  221.     m_bSettingFragment(FALSE),
  222.     m_bFragFoundAndResolved(FALSE),
  223.     m_ulFragmentTimeOffset(0),
  224.     m_bInHyperlink(FALSE),
  225.     m_pStatusMessage(0),
  226.     m_bStatusMessageSet(FALSE),
  227.     m_bMetadataPassedOffAlready(FALSE),
  228.     m_pPersistentLayoutStream(NULL),
  229.     m_bIsRootLayoutSetup(FALSE),
  230.     m_ulNoLayoutRendererCount(0),
  231.     m_pErrorMessages(NULL),
  232.     m_bDestPlaystateIsPause(FALSE),
  233. #ifdef _WINDOWS
  234.     m_hPreHyperlinkCursor(0),
  235.     m_hHyperlinkCursor(0),
  236.     m_bNeedToSetHyperlinkCursor(FALSE),
  237. #endif
  238. #ifdef _MACINTOSH
  239.     m_hHyperlinkCursor(0),
  240.     m_bResetCursor(FALSE),
  241. #endif
  242. #if defined(_UNIX)  &&  (!(defined(_BEOS)))  &&  defined(USE_XWINDOWS)
  243.     m_hHyperlinkCursor(0),
  244.     m_hCurrentCursor(0),
  245.     m_pDisplay(0),
  246.     m_Window(0),
  247.     m_pPixmapDisplay(NULL),
  248.     m_pVisualInfo(NULL),
  249. #endif
  250.     m_bSiteLayoutComplete(FALSE),
  251.     m_nFragmentTracks(0),
  252.     m_dResizeXScale(1.0),
  253.     m_dResizeYScale(1.0),
  254.     m_pActiveTransitions(NULL),
  255.     m_pActiveAnimations(NULL),
  256.     m_pRegionMapIterator(NULL),
  257.     m_pAnimationMap(NULL),
  258.     m_pDelayedRendererCloseList(NULL),
  259.     m_bSMILPresentationHasEnded(FALSE),
  260.     m_pSMILDefaultNamespaceStr(NULL),
  261.     m_pViewPortManager(NULL)
  262. #ifdef XXXMEH_DO_VIEWPORT_TLC
  263.     ,m_pViewPortSiteMap(NULL)
  264.     ,m_bSMILViewportClose(FALSE)
  265. #endif
  266.     , m_pPlayerResumeStack(NULL)
  267. #if defined(BE_SITE_SUPPLIER_20010205)
  268.     , m_pIndependentPlayer(NULL)
  269.     , m_pChildSiteInfoMap(NULL)
  270. #endif /* BE_SITE_SUPPLIER_20010205 */
  271.     , m_ulGroupIndex(0)
  272.     , m_ulTrackIndex(0)
  273.     , m_uGroupIndexWithin(0)
  274.     , m_bSitesDetached(FALSE)
  275.     , m_ulPersistentComponentID(0)
  276.     , m_uPersistentGroupID(0)
  277.     , m_uPersistentTrackID(0)
  278.     , m_pPersistentProperties(NULL)
  279.     , m_pPersistentParentRenderer(NULL)
  280.     , m_pExternalMediaMarkerList(NULL)
  281.     , m_bLayoutElementPresent(FALSE)
  282.     , m_bEmptyLayout(FALSE)
  283.     , m_bDoNotZoom(FALSE)
  284.     , m_AnimationIterator(NULL)
  285.     , m_pAnimSiteRedrawMap(NULL)
  286.     , m_pAnimRegionRecomputeMap(NULL)
  287.     , m_bAnimateRootLayout(FALSE)
  288.     , m_pAnimTopLayoutMap(NULL)
  289.     , m_usAnimBaseGroupIndex(0)
  290.     , m_ulAnimDuration(0)
  291.     , m_ulCurGroupDuration(0)
  292.     , m_pSoundLevelMutex(NULL)
  293.     , m_bCloseCalled(FALSE)
  294.     , m_bRootLayoutSiteDetached(FALSE)
  295.     , m_pHandlePendingSchedulingCallback(NULL)
  296.     , m_pHyperlinkCallback(NULL)
  297.     , m_pMediaID2RendererMap(NULL)
  298.     , m_pMediaID2RendererSiteMap(NULL)
  299.     , m_pMediaID2RendererSiteWatcherMap(NULL)
  300.     , m_pEventSinkList(NULL)
  301.     , m_ulPktnum(0)
  302.     , m_usOldXPos(0)
  303.     , m_usOldYPos(0)
  304. {
  305.     m_pContext = pContext;
  306.     HX_ASSERT(m_pContext);
  307.     if(m_pContext)
  308.     {
  309. m_pContext->AddRef();
  310. HX_VERIFY(HXR_OK == m_pContext->
  311.   QueryInterface(IID_IHXSiteManager,(void**)&m_pSiteMgr));
  312. HX_VERIFY(HXR_OK == m_pContext->
  313.   QueryInterface(IID_IHXScheduler, (void**)&m_pScheduler));
  314. if (HXR_OK != m_pContext->QueryInterface(IID_IHXStatusMessage,
  315.  (void**)&m_pStatusMessage))
  316. {
  317.     // not an error, just a feature waiting to happen...
  318.     m_pStatusMessage = NULL;
  319. }
  320. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  321.         // QI for IHXViewPortManager
  322.         m_pContext->QueryInterface(IID_IHXViewPortManager,
  323.                                    (void**) &m_pViewPortManager);
  324.         if (m_pViewPortManager)
  325.         {
  326.             // Add ourselves as a view port sink
  327.             IHXViewPortSink* pSink = NULL;
  328.             QueryInterface(IID_IHXViewPortSink, (void**) &pSink);
  329.             if (pSink)
  330.             {
  331.                 m_pViewPortManager->AddViewPortSink(pSink);
  332.             }
  333.             HX_RELEASE(pSink);
  334.         }
  335. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  336.         // Add ourselves as a media marker sink
  337.         // TRUE adds us, FALSE removes us
  338.         addRemoveMediaMarkerSink(TRUE);
  339.         // Add ourselves as an error sink
  340.         addRemoveErrorSink(TRUE);
  341.         // QI for IHXErrorMessages - ok if not implemented
  342.         m_pContext->QueryInterface(IID_IHXErrorMessages,
  343.                                    (void**) &m_pErrorMessages);
  344.     }
  345. #ifdef _WINDOWS
  346.     m_hHyperlinkCursor = LoadCursor(g_hInstance,
  347.         MAKEINTRESOURCE(IDC_HANDCURSOR));
  348. #endif
  349. #ifdef _MACINTOSH
  350.     const short HAND_CURSOR  = 1313;
  351.     m_pResourceLoader = CResourceLoader::CreateInstance(g_DLLFSpec);
  352.     m_hHyperlinkCursor = (CursHandle)m_pResourceLoader->LoadResource('CURS', HAND_CURSOR);
  353. #endif
  354.     
  355. #ifdef _DEBUG
  356.     BOOL bShowDependencies = FALSE;
  357.     ::getBooleanPreference(m_pContext,
  358.                            "showdependencies",
  359.                            bShowDependencies);
  360.     if(bShowDependencies)
  361.     {
  362. // mark file boundary
  363. #ifdef _WINDOWS
  364.         const char* pszDepFile = "\smildep.txt";
  365. #else
  366.         const char* pszDepFile = "smildep.txt";
  367. #endif
  368. FILE* fp = fopen(pszDepFile, "a");
  369. if(fp)
  370. {
  371.          fprintf(fp, "===========================n");
  372.     fclose(fp);
  373. }
  374.     }
  375. #endif
  376. }
  377. CSmilDocumentRenderer::~CSmilDocumentRenderer()
  378. {
  379.     HX_RELEASE(m_pSiteMgr);
  380.     HX_DELETE(m_pRootLayout);
  381. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  382.     closeViewports();
  383.     removeViewports();
  384.     HX_DELETE(m_pViewportList);
  385.     HX_RELEASE(m_pViewPortManager);
  386. #ifdef XXXMEH_DO_VIEWPORT_TLC
  387.     clearViewportMap();
  388. #endif
  389. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  390.     HX_DELETE(m_pRegPointMap);
  391.     HX_RELEASE(m_pPersistentLayoutStream);
  392.     HX_RELEASE(m_pErrorMessages);
  393. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  394.     removeActiveAnimations();
  395. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  396.     HX_DELETE(m_pActiveAnimations);
  397.     HX_DELETE(m_pAnimationMap);
  398.     HX_DELETE(m_pAnimSiteRedrawMap);
  399.     HX_DELETE(m_pAnimRegionRecomputeMap);
  400.     HX_DELETE(m_pAnimTopLayoutMap);
  401.     deleteExternalMediaMarkerList();
  402.     HX_RELEASE(m_pSMILDefaultNamespaceStr);
  403.     if (m_pPrefetchTrackElementMap)
  404.     {
  405. CHXMapLongToObj::Iterator i;
  406. for (i = m_pPrefetchTrackElementMap->Begin();
  407. i != m_pPrefetchTrackElementMap->End(); ++i)
  408. {
  409.     CHXString* pId = (CHXString*)(*i);
  410.     HX_DELETE(pId);
  411. }
  412. HX_DELETE(m_pPrefetchTrackElementMap);
  413.     }
  414.     if (m_pIndependentPlayer)
  415.     {
  416. HX_DELETE(m_pIndependentPlayer);
  417.     }
  418.     if (m_pChildSiteInfoMap)
  419.     {
  420. HX_ASSERT(m_pChildSiteInfoMap->IsEmpty()); // /Should be empty!...
  421. // ...but in case it's not empty, go ahead and delete its nodes:
  422. CHXMapLongToObj::Iterator i = m_pChildSiteInfoMap->Begin();
  423. for(; i != m_pChildSiteInfoMap->End(); ++i)
  424. {
  425.     SMILChildSiteInfo* pChildSiteInfo = (SMILChildSiteInfo*)(*i);
  426.     delete pChildSiteInfo;
  427. }
  428. HX_DELETE(m_pChildSiteInfoMap);
  429.     }
  430. #if defined(_UNIX)  &&  (!(defined(_BEOS)))  &&  defined(USE_XWINDOWS)
  431.     CHXMapPtrToPtr::Iterator i = m_siteToXDataMap.Begin();
  432.     for(; i != m_siteToXDataMap.End(); ++i)
  433.     {
  434.         XData* xData = (XData*)(*i);
  435. delete xData;
  436.     }
  437.     if (m_pVisualInfo)
  438.     {
  439. XFree(m_pVisualInfo);
  440. m_pVisualInfo = NULL;
  441.     }
  442.     if (m_pDisplay && m_hHyperlinkCursor)
  443.     {
  444. XFreeCursor(m_pDisplay, m_hHyperlinkCursor);
  445. m_hHyperlinkCursor = 0;
  446.     }
  447. #endif    
  448. #if defined(_MACINTOSH)
  449.     if (m_hHyperlinkCursor)
  450.     {
  451.      m_pResourceLoader->UnloadResource((Handle)m_hHyperlinkCursor);
  452.      m_hHyperlinkCursor = NULL;
  453.     
  454.      HX_RELEASE(m_pResourceLoader);
  455.     }
  456.     if (m_bResetCursor)
  457.     {
  458. ::InitCursor();
  459.     }
  460. #endif
  461.     HX_RELEASE(m_pSoundLevelMutex);
  462.     clearRendererMap();
  463.     HX_DELETE(m_pMediaID2RendererMap);
  464.     clearRendererSiteMap();
  465.     HX_DELETE(m_pMediaID2RendererSiteMap);
  466.     clearRendererSiteWatcherMap();
  467.     HX_DELETE(m_pMediaID2RendererSiteWatcherMap);
  468.     destroyAllRegions();
  469.     CleanUpSiteInfoContainers();
  470.     HX_DELETE(m_pSiteWatcherMap);
  471. }
  472. /*
  473.  * IUnknown methods
  474.  */
  475. STDMETHODIMP
  476. CSmilDocumentRenderer::QueryInterface(REFIID riid, void** ppvObj)
  477. {
  478.     if(IsEqualIID(riid, IID_IUnknown))
  479.     {
  480. AddRef();
  481. *ppvObj = this;
  482. return HXR_OK;
  483.     }
  484.     else if(IsEqualIID(riid, IID_IHXSiteUser))
  485.     {
  486. HX_ASSERT(0  &&  "Huh?!  CSmilDocumentRenderer doesn't implement IHXSiteUser");
  487. AddRef();
  488. *ppvObj = (IHXSiteUser*)this;
  489. return HXR_OK;
  490.     }
  491.     else if(IsEqualIID(riid, IID_IHXRendererAdviseSink))
  492.     {
  493. AddRef();
  494. *ppvObj = (IHXRendererAdviseSink*)this;
  495. return HXR_OK;
  496.     }
  497.     else if(IsEqualIID(riid, IID_IHXGroupSink))
  498.     {
  499. AddRef();
  500. *ppvObj = (IHXGroupSink*)this;
  501. return HXR_OK;
  502.     }
  503.     else if(IsEqualIID(riid, IID_IHXClientAdviseSink))
  504.     {
  505. AddRef();
  506. *ppvObj = (IHXClientAdviseSink*)this;
  507. return HXR_OK;
  508.     }
  509.     else if (IsEqualIID(riid, IID_IHXPrefetchSink))
  510.     {
  511. AddRef();
  512. *ppvObj = (IHXPrefetchSink*)this;
  513. return HXR_OK;
  514.     }
  515.     else if (IsEqualIID(riid, IID_IHXTrackSink))
  516.     {
  517. AddRef();
  518. *ppvObj = (IHXTrackSink*)this;
  519. return HXR_OK;
  520.     }
  521. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  522.     else if (IsEqualIID(riid, IID_IHXViewPortSink))
  523.     {
  524. AddRef();
  525. *ppvObj = (IHXViewPortSink*) this;
  526. return HXR_OK;
  527.     }
  528. #ifdef XXXMEH_DO_VIEWPORT_TLC
  529.     else if (IsEqualIID(riid, IID_IHXViewPortSupplier))
  530.     {
  531. AddRef();
  532. *ppvObj = (IHXViewPortSupplier*) this;
  533. return HXR_OK;
  534.     }
  535. #endif
  536. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  537. #if defined(BE_SITE_SUPPLIER_20010205)
  538.     else if (IsEqualIID(riid, IID_IHXSiteSupplier))
  539.     {
  540. AddRef();
  541. *ppvObj = (IHXSiteSupplier*) this;
  542. return HXR_OK;
  543.     }
  544. #endif /* BE_SITE_SUPPLIER_20010205 */
  545.     else if (IsEqualIID(riid, IID_IHXMediaMarkerSink))
  546.     {
  547. AddRef();
  548. *ppvObj = (IHXMediaMarkerSink*) this;
  549. return HXR_OK;
  550.     }
  551.     else if (IsEqualIID(riid, IID_IHXEventSink))
  552.     {
  553. AddRef();
  554. *ppvObj = (IHXEventSink*) this;
  555. return HXR_OK;
  556.     }
  557.     else if (IsEqualIID(riid, IID_IHXErrorSink))
  558.     {
  559. AddRef();
  560. *ppvObj = (IHXErrorSink*) this;
  561. return HXR_OK;
  562.     }
  563.     *ppvObj = NULL;
  564.     return HXR_NOINTERFACE;
  565. }
  566. STDMETHODIMP_(ULONG32)
  567. CSmilDocumentRenderer::AddRef()
  568. {
  569.     return InterlockedIncrement(&m_lRefCount);
  570. }
  571. STDMETHODIMP_(ULONG32)
  572. CSmilDocumentRenderer::Release()
  573. {
  574.     if(InterlockedDecrement(&m_lRefCount) > 0)
  575.     {
  576. return m_lRefCount;
  577.     }
  578.     delete this;
  579.     return 0;
  580. }
  581. HX_RESULT
  582. CSmilDocumentRenderer::close(CSmilRenderer* pParent)
  583. {
  584.     MLOG_LEAKCHECK("CSmilDocumentRenderer::close() t=%lun", HX_GET_BETTERTICKCOUNT());
  585.     if (m_pHandlePendingSchedulingCallback &&
  586. m_pHandlePendingSchedulingCallback->m_bIsCallbackPending)
  587.     {
  588. m_pHandlePendingSchedulingCallback->m_bIsCallbackPending = FALSE;
  589. m_pScheduler->Remove(m_pHandlePendingSchedulingCallback->m_PendingHandle);
  590. m_pHandlePendingSchedulingCallback->m_PendingHandle = 0;
  591.     }
  592.     HX_RELEASE(m_pHandlePendingSchedulingCallback);
  593.     if (m_pHyperlinkCallback &&
  594. m_pHyperlinkCallback->IsCallbackPending())
  595.     {
  596. m_pHyperlinkCallback->SetCallbackPending(FALSE);
  597. m_pScheduler->Remove(m_pHyperlinkCallback->GetCallbackHandle());
  598. m_pHyperlinkCallback->SetCallbackHandle(0);
  599.     }
  600.     HX_RELEASE(m_pHyperlinkCallback);
  601.     if (m_pDelayedRendererCloseList)
  602.     {
  603. CHXSimpleList::Iterator i = m_pDelayedRendererCloseList->Begin();
  604. for (; i != m_pDelayedRendererCloseList->End(); ++i)
  605. {
  606.     SMILDelayedRendererClose* pClose= (SMILDelayedRendererClose*)(*i);
  607.     //HX_ASSERT(FALSE); ??
  608.     actualRendererClosed(pClose->m_pRenderer, pClose->m_pInfo);
  609.     HX_RELEASE(pClose->m_pRenderer);
  610.     HX_RELEASE(pClose->m_pInfo);
  611.     HX_DELETE(pClose);
  612. }
  613.     }
  614.     HX_DELETE(m_pDelayedRendererCloseList);
  615.     if (m_pRootLayout && m_pRootLayout->m_pSiteUser)
  616.     {
  617.         IUnknown* pThisUnk = NULL;
  618.         m_pRootLayout->m_pSiteUser->QueryInterface(IID_IUnknown, (void**) &pThisUnk);
  619.         if (pThisUnk)
  620.         {
  621.             pParent->HandleRemoveLayoutSiteGroup(pThisUnk);
  622.         }
  623.         HX_RELEASE(pThisUnk);
  624.     }
  625.     m_pParent = NULL;
  626.     if(m_pEventList)
  627.     {
  628. CHXSimpleList::Iterator i = m_pEventList->Begin();
  629. for(; i != m_pEventList->End(); ++i)
  630. {
  631.     CSmilLayoutEvent* pEvent = (CSmilLayoutEvent*)(*i);
  632.     delete pEvent;
  633. }
  634.     }
  635.     HX_DELETE(m_pEventList);
  636.     removeAllPlayToAssoc();
  637.     deleteExternalMediaMarkerList();
  638. //    HX_DELETE(m_pRootLayout);
  639. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  640.     closeViewports();
  641.     removeViewports();
  642.     HX_DELETE(m_pViewportList);
  643. #ifdef XXXMEH_DO_VIEWPORT_TLC
  644.     clearViewportMap();
  645. #endif
  646.     // Remove ourselves as a view port sink
  647.     if (m_pViewPortManager)
  648.     {
  649.         IHXViewPortSink* pSink = NULL;
  650.         QueryInterface(IID_IHXViewPortSink, (void**) &pSink);
  651.         if (pSink)
  652.         {
  653.             m_pViewPortManager->RemoveViewPortSink(pSink);
  654.         }
  655.         HX_RELEASE(pSink);
  656.     }
  657.     HX_RELEASE(m_pViewPortManager);
  658. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  659.     HX_DELETE(m_pRegPointMap);
  660.     HX_RELEASE(m_pSMILDefaultNamespaceStr);
  661. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  662.     removeActiveAnimations();
  663. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  664.     HX_DELETE(m_pActiveAnimations);
  665.     HX_DELETE(m_pAnimSiteRedrawMap);
  666.     HX_DELETE(m_pAnimRegionRecomputeMap);
  667.     HX_DELETE(m_pAnimTopLayoutMap);
  668.     // Remove ourselves as a media marker sink
  669.     // TRUE adds us, FALSE removes us
  670.     addRemoveMediaMarkerSink(FALSE);
  671.     // Are we setup as an event sink?
  672.     if (m_bEventSinkWasSetup)
  673.     {
  674.         // Remove ourselves as an event sink,
  675.         // TRUE adds us, FALSE removes us
  676.         addRemoveEventSink(FALSE);
  677.     }
  678.     // Remove any renderer event sinks we have setup
  679.     removeAllEventSinks();
  680.     HX_DELETE(m_pEventSinkList);
  681.     // Remove ourselve as an error sink
  682.     addRemoveErrorSink(FALSE);
  683.     HX_RELEASE(m_pErrorMessages);
  684.     if (m_bRootLayoutSiteDetached)
  685.     {
  686.         destroyAllRegions();
  687.     }
  688.     
  689. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  690.     if(m_pTransitionMap)
  691.     {
  692. CHXMapStringToOb::Iterator i = m_pTransitionMap->Begin();
  693. for(; i != m_pTransitionMap->End(); ++i)
  694. {
  695.     CSmilTransitionInfo* pTrans = (CSmilTransitionInfo*)(*i);
  696.     delete pTrans;
  697. }
  698.     }
  699.     HX_DELETE(m_pTransitionMap);
  700. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  701.     if (m_pActiveTransitions)
  702.     {
  703. CHXSimpleList::Iterator i = m_pActiveTransitions->Begin();
  704. for (;i != m_pActiveTransitions->End(); ++i)
  705. {
  706.     SMILTransitionState* pState = (SMILTransitionState*)*i;
  707.     HX_DELETE(pState);
  708. }
  709.     }
  710.     HX_DELETE(m_pActiveTransitions);
  711.     if(m_pGroupInfoMap)
  712.     {
  713. CHXMapLongToObj::Iterator i = m_pGroupInfoMap->Begin();
  714. for(; i != m_pGroupInfoMap->End(); ++i)
  715. {
  716.     SMILGroupInfo* pGroupInfo = (SMILGroupInfo*)(*i);
  717.     delete pGroupInfo;
  718. }
  719.     }
  720.     HX_DELETE(m_pGroupInfoMap);
  721.     if(m_pDeferredSourceMap)
  722.     {
  723. CHXMapStringToOb::Iterator i = m_pDeferredSourceMap->Begin();
  724. for(; i != m_pDeferredSourceMap->End(); ++i)
  725. {
  726.     SMILDeferredSourceInfo* pInfo = (SMILDeferredSourceInfo*)(*i);
  727.     delete pInfo;
  728. }
  729.     }
  730.     HX_DELETE(m_pDeferredSourceMap);
  731.     if(m_pDeferrededRemoveTrackMap)
  732.     {
  733. CHXMapStringToOb::Iterator i = m_pDeferrededRemoveTrackMap->Begin();
  734. for(; i != m_pDeferrededRemoveTrackMap->End(); ++i)
  735. {
  736.     CHXString* pID = (CHXString*)(*i);
  737.     delete pID;
  738. }
  739.     }
  740.     HX_DELETE(m_pDeferrededRemoveTrackMap);
  741.     if (m_pPausedAndDisabledIDMap)
  742.     {
  743. CHXMapStringToOb::Iterator i = m_pPausedAndDisabledIDMap->Begin();
  744. for(; i != m_pPausedAndDisabledIDMap->End(); ++i)
  745. {
  746.     CHXString* pID = (CHXString*)(*i);
  747.     delete pID;
  748. }
  749.     }
  750.     HX_DELETE(m_pPausedAndDisabledIDMap);
  751.     
  752.     if (m_pPausedAndDisabledBrightnessMap)
  753.     {
  754. CHXMapStringToOb::Iterator i =
  755. m_pPausedAndDisabledBrightnessMap->Begin();
  756. for (; i != m_pPausedAndDisabledBrightnessMap->End(); ++i)
  757. {
  758.     float* pf = (float*)(*i);
  759.     delete pf;
  760. }
  761.     }
  762.     HX_DELETE(m_pPausedAndDisabledBrightnessMap);
  763.     if(m_pStatusMessage)
  764.     {
  765. m_pStatusMessage->SetStatus(NULL);
  766.     }
  767.     HX_RELEASE(m_pStatusMessage);
  768.     if (m_pPlayerResumeStack)
  769.     {
  770. CSmilPlayerResumePos* pResumePos =
  771. (CSmilPlayerResumePos*)m_pPlayerResumeStack->Pop();
  772. while (pResumePos)
  773. {
  774.     delete pResumePos;
  775.     pResumePos = (CSmilPlayerResumePos*)m_pPlayerResumeStack->Pop();
  776. }
  777.     }
  778.     HX_DELETE(m_pPlayerResumeStack);
  779.     if (m_bRootLayoutSiteDetached)
  780.     {
  781.         CleanUpSiteInfoContainers();
  782.         HX_DELETE(m_pSiteWatcherMap);
  783.     }
  784.     HX_DELETE(m_pSmilParser);
  785.     HX_VECTOR_DELETE(m_pFragment);
  786.     HX_RELEASE(m_pScheduler);
  787.     HX_RELEASE(m_pContext);
  788.     clearRendererMap();
  789.     HX_DELETE(m_pMediaID2RendererMap);
  790.     clearRendererSiteMap();
  791.     HX_DELETE(m_pMediaID2RendererSiteMap);
  792.     clearRendererSiteWatcherMap();
  793.     HX_DELETE(m_pMediaID2RendererSiteWatcherMap);
  794. #ifdef _MACINTOSH
  795.     if (m_bResetCursor)
  796.     {
  797. m_bResetCursor = FALSE;
  798. ::InitCursor();
  799.     }
  800. #endif
  801.     // Set the flag indicating that close has been called
  802.     m_bCloseCalled = TRUE;
  803.     // Release the sound level mutex
  804.     HX_RELEASE(m_pSoundLevelMutex);
  805.     return HXR_OK;
  806. }
  807. HX_RESULT
  808. CSmilDocumentRenderer::onHeader(IHXValues* pHeader)
  809. {
  810.     m_bSMILPresentationHasEnded = FALSE;
  811.     m_pRegionMap = new CHXMapStringToOb;
  812.     m_pSiteInfoByRendererMap = new CHXMapPtrToPtr;
  813.     m_pSmilParser = new CSmilParser(m_pContext);
  814.     m_pSmilParser->init();
  815.     
  816.     if (m_pPersistentParentRenderer &&
  817. HXR_OK == m_pPersistentParentRenderer->GetElementProperties(m_uPersistentGroupID,
  818.     m_uPersistentTrackID,
  819.     m_pPersistentProperties))
  820.     {
  821. m_pSmilParser->InitPersistent(m_ulPersistentComponentID, m_pPersistentProperties);
  822.     }
  823.     // Create a root-layout object
  824.     HX_DELETE(m_pRootLayout);
  825.     m_pRootLayout = new CSmilBasicRootLayout();
  826.     // The SMIL default namespace is stored in the
  827.     // "MimeType" property of the stream header
  828.     if (pHeader)
  829.     {
  830.         HX_RELEASE(m_pSMILDefaultNamespaceStr);
  831. if (m_pParent  &&  !m_pParent->isStreamProxiedByOtherRenderer())
  832. {
  833.     pHeader->GetPropertyCString("MimeType", m_pSMILDefaultNamespaceStr);
  834. }
  835. else // /Use value passed in via IHXSmilToSmilRendererCommunicator
  836. {
  837.     HX_ASSERT(m_pParent);
  838.     if (m_pParent  &&  m_pParent->m_pVersionNamespaceFromProxyRenderer)
  839.     {
  840. m_pSMILDefaultNamespaceStr =
  841. m_pParent->m_pVersionNamespaceFromProxyRenderer;
  842. m_pSMILDefaultNamespaceStr->AddRef();
  843.     }
  844. }
  845.     }
  846.     // Get the group we are starting on
  847.     m_usAnimBaseGroupIndex = getCurrentGroup();
  848.     return HXR_OK;
  849. }
  850. HX_RESULT
  851. CSmilDocumentRenderer::getErrorInfo(REF(UINT32) ulLineNumber,
  852.     REF(UINT32) ulColumnNumber,
  853.     REF(IHXBuffer*) pErrorText)
  854. {
  855.     ulLineNumber = m_pSmilParser->m_ulErrorLineNumber;
  856.     ulColumnNumber = m_pSmilParser->m_ulErrorColumnNumber;
  857.     pErrorText = m_pSmilParser->m_pErrorText;
  858.     if(pErrorText)
  859.     {
  860. pErrorText->AddRef();
  861.     }
  862.     return HXR_OK;
  863. }
  864. HX_RESULT CSmilDocumentRenderer::getErrorInterface(REF(IHXErrorMessages*) rpErrMsgs)
  865. {
  866.     HX_RESULT retVal = HXR_OK;
  867.     if (m_pErrorMessages)
  868.     {
  869.         HX_RELEASE(rpErrMsgs);
  870.         rpErrMsgs = m_pErrorMessages;
  871.         rpErrMsgs->AddRef();
  872.     }
  873.     else
  874.     {
  875.         retVal = HXR_FAIL;
  876.     }
  877.     return retVal;
  878. }
  879. HX_RESULT
  880. CSmilDocumentRenderer::onPacket(IHXBuffer* pBuffer, BOOL bIsLast)
  881. {
  882.     HX_RESULT rc = HXR_OK;
  883.     BOOL bDumpToFile = FALSE;
  884.     ::getBooleanPreference(m_pContext,
  885.                            "NonObviousKeyName",
  886.                            bDumpToFile);
  887.     BOOL bShowPacketBoundaries = FALSE;
  888.     ::getBooleanPreference(m_pContext,
  889.                            "NonObviousKeyNameOption1",
  890.                            bShowPacketBoundaries);
  891.     if (bDumpToFile)
  892.     {
  893. #ifdef _WINDOWS
  894.         const char* pszFile = "c:\smildump.txt";
  895. #else
  896.         const char* pszFile = "smildump.txt";
  897. #endif
  898.         FILE* pFoo = fopen(pszFile, m_ulPktnum > 0L ? "a" : "w");
  899.         if (pFoo)
  900.         {
  901.             char* pBuf = (char*) pBuffer->GetBuffer();
  902.             if(pBuf && strlen(pBuf) > 0)
  903.             {
  904.                 if (bShowPacketBoundaries)
  905.                 {
  906.                     fprintf(pFoo, "[[[packet # %lu]]]:{{{", m_ulPktnum);
  907.                 }
  908.                 fwrite(pBuf, 1, pBuffer->GetSize(), pFoo);
  909.                 if (bShowPacketBoundaries)
  910.                 {
  911.                     fprintf(pFoo, "}}}n");
  912.                 }
  913.             }
  914.             else
  915.             {
  916.                 if (bShowPacketBoundaries)
  917.                 {
  918.                     fprintf(pFoo, "n[[[Packet %lu empty in onPacket()]]]n",
  919.                             m_ulPktnum);
  920.                 }
  921.             }
  922.         }
  923.         fclose(pFoo);
  924.         if (bIsLast)
  925.             m_ulPktnum = 0L;
  926.         else
  927.             m_ulPktnum++;
  928.     }
  929.     rc = m_pSmilParser->parse(pBuffer, bIsLast);
  930.     return rc;
  931. }
  932. HX_RESULT CSmilDocumentRenderer::setDocument(const char* pFragment)
  933. {
  934.     BOOL bDisableValidation = FALSE;
  935.     ::getBooleanPreference(m_pContext,
  936.                            "DisableSMILValidation",
  937.                            bDisableValidation);
  938.     HX_RESULT rc = HXR_OK;
  939.     if (!bDisableValidation)
  940.     {
  941. #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
  942.         rc = m_pSmilParser->validateAgainstDTD();
  943. #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
  944.     }
  945.     if (SUCCEEDED(rc))
  946.     {
  947.         rc = m_pSmilParser->createElements();
  948.         if(HXR_OK == rc)
  949.         {
  950.             rc = m_pSmilParser->setAllElementHandlers(this);
  951.             rc = handleElements();
  952.             if (SUCCEEDED(rc))
  953.             {
  954.                 rc = postParseSetup();
  955.             }
  956.             // The player may need to know about the URLs 
  957.             // we will hurl in advance. Therefore, we will
  958.             // throw all the potential URLs we may throw
  959.             // to the IHXHyperNavigateHint interface.
  960.             SendHyperlinkHints();
  961.             // Handle any references to external media marker files
  962.             m_pSmilParser->handleAllXMMFReferences();
  963.             BOOL bContainsSource = m_pSmilParser->presentationContainsASource();
  964.     BOOL bContainsInitiallyScheduledTrack =
  965.     m_pSmilParser->presentationContainsInitiallyScheduledTrack();
  966.             ULONG32 ulDurIfNoInitialTracksScheduled =
  967.                     m_pSmilParser->presentationDurIfNoInitialTracksScheduled();
  968.             // If we have a source in the tree but no source has
  969.             // been scheduled, then we'll go ahead and create a group
  970.             // XXXMEH - temporary fix. The core does not call DoneChangeLayout
  971.             // on the TLC if there is no source scheduled. The real fix for
  972.             // this should be done in the core/TLC but may be involved.
  973.             // This fix should do in the meantime.
  974.             if (!bContainsSource || !bContainsInitiallyScheduledTrack)
  975.             {
  976.                 setupDummySource();
  977.             }
  978.             IHXPlayer* pPlayer = m_pParent->getPlayer();
  979.             IHXGroupManager* pMgr = 0;
  980.             if(HXR_OK == pPlayer->QueryInterface(IID_IHXGroupManager, (void**)&pMgr))
  981.             {
  982.                 if(pFragment)
  983.                 {
  984.                     m_pFragment = new_string(pFragment);
  985.                     m_bSettingFragment = TRUE;
  986.                     m_nFragmentTracks = 0;
  987.                     UINT16 uFragmentGroup = 
  988.                         m_pSmilParser->getFragmentGroup(m_pFragment);
  989.                     pMgr->SetCurrentGroup(uFragmentGroup);
  990.                 }
  991.                 else if (bContainsInitiallyScheduledTrack)
  992.                 {
  993.     if (m_pParent->m_bUseNestedMeta && m_uCurrentGroupIndex == -1)
  994.     {
  995. pMgr->GetCurrentGroup((UINT16&)m_uCurrentGroupIndex);
  996.     }
  997.                     else
  998.                     {
  999.                         pMgr->SetCurrentGroup(0);
  1000.                     }
  1001.                 }
  1002. // /No sources were scheduled to play, so we have to manually
  1003. // keep the presentation open for others like animate elements
  1004. // (which can animate regions and thus no sources are needed
  1005. // for a SMIL presentation to be (arguably) interesting.  Also,
  1006. // a track (source) could begin on an event during playback:
  1007.                 else if (ulDurIfNoInitialTracksScheduled>0  &&
  1008. SMILTIME_INVALID != ulDurIfNoInitialTracksScheduled)
  1009.                 {
  1010.                     HX_ASSERT(m_pPersistentLayoutStream);
  1011.                     if (m_pPersistentLayoutStream)
  1012.                     {
  1013.                         IHXValues* pStreamProps = NULL;
  1014.                         if(HXR_OK == m_pPersistentLayoutStream->GetProperties(pStreamProps))
  1015.                         {
  1016.                             pStreamProps->SetPropertyULONG32("duration",
  1017.                                     ulDurIfNoInitialTracksScheduled);
  1018.                             m_pPersistentLayoutStream->SetProperties(pStreamProps);
  1019.                             HX_RELEASE(pStreamProps);
  1020.                         }
  1021.                     }
  1022.                     // XXXMEH - since there are no sources, the only sites will
  1023.                     // be region sites, so unless they have an explicit
  1024.                     // showBackground="whenActive", then we need to show them here
  1025.                     showAllSites(m_pRootLayout, TRUE);
  1026.                 }
  1027.                 pMgr->Release();
  1028.             }
  1029.         }
  1030.     }
  1031.     return rc;
  1032. }
  1033. HX_RESULT CSmilDocumentRenderer::setupDummySource()
  1034. {
  1035.     HX_RESULT retVal = HXR_FAIL;
  1036.     // Our dummy source is a <brush>, so if <brush> is
  1037.     // not supported, then we fail.
  1038. #if defined(HELIX_FEATURE_SMIL2_BRUSH)
  1039.     if (m_pParent)
  1040.     {
  1041.         // Get the player
  1042.         IHXPlayer* pPlayer = m_pParent->getPlayer();
  1043.         if (pPlayer)
  1044.         {
  1045.             // Get the group manager
  1046.             IHXGroupManager* pMgr = NULL;
  1047.             pPlayer->QueryInterface(IID_IHXGroupManager, (void**) &pMgr);
  1048.             if (pMgr)
  1049.             {
  1050.                 // Get the current group
  1051.                 UINT16 usGroup = 0;
  1052.         if (m_pParent->m_bUseNestedMeta && m_uCurrentGroupIndex == -1)
  1053.         {
  1054.     pMgr->GetCurrentGroup(usGroup);
  1055.         }
  1056.                 // Get an IHXCommonClassFactory
  1057.                 IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  1058.                 if (pFactory)
  1059.                 {
  1060.                     // Create an IHXValues for the track properties
  1061.                     IHXValues* pValues = NULL;
  1062.                     pFactory->CreateInstance(CLSID_IHXValues, (void**) &pValues);
  1063.                     if (pValues)
  1064.                     {
  1065.                         // Create an IHXValues for the 822 headers
  1066.                         IHXValues* pReqHeaders = NULL;
  1067.                         pFactory->CreateInstance(CLSID_IHXValues, (void**) &pReqHeaders);
  1068.                         if (pReqHeaders)
  1069.                         {
  1070.                             // Create the base of our src string
  1071.                             CHXString cSrc("data:text/brush;base64,");
  1072.                             // Now we need to create our brush string
  1073.                             CHXString cBrushText("<brush color="black"/>");
  1074.                             // Allocate an output string big enough to hold the
  1075.                             // base-64-encoded string
  1076.                             char* pStr64 = new char [cBrushText.GetLength() << 1];
  1077.                             if (pStr64)
  1078.                             {
  1079.                                 // Encode to base-64
  1080.                                 INT32 lEncodedLen = BinTo64((const BYTE*)(const char*) cBrushText,
  1081.                                                             cBrushText.GetLength(),
  1082.                                                             pStr64);
  1083.                                 // Create a string out of this encoded data
  1084.                                 CHXString cEncodedBrushText((const char*) pStr64, lEncodedLen);
  1085.                                 // Append this string to our src string
  1086.                                 cSrc += cEncodedBrushText;
  1087.                             }
  1088.                             HX_VECTOR_DELETE(pStr64);
  1089.                             // Assign the "url" property
  1090.                             setProperty(pValues, "url", (const char*) cSrc);
  1091.                             // Assign the "id" property
  1092.                             setProperty(pValues, "id", "dummy_brush_07241965");
  1093.                             // Assign the delay property
  1094.                             pValues->SetPropertyULONG32("delay", 0);
  1095.                             // Assign the duration property to 1ms
  1096.                             pValues->SetPropertyULONG32("duration", 1);
  1097.                             
  1098.                             //Set the PersistentComponentID.
  1099.                             pValues->SetPropertyULONG32("PersistentComponentID", m_ulPersistentComponentID);
  1100.                             //Tell the core this we don't want any
  1101.                             //TrackAdded callbacks because we don't
  1102.                             //have any groups.
  1103.                             pValues->SetPropertyULONG32("NoGroupsPresent", 1);
  1104.                             // Add the "NullBrush" property to the request headers
  1105.                             setProperty(pReqHeaders, "NullBrush", "1");
  1106.                             // Get the current group
  1107.                             IHXGroup* pGroup = NULL;
  1108.                             pMgr->GetGroup(usGroup, pGroup);
  1109.                             if (pGroup)
  1110.                             {
  1111.                                 // Get the IHXGroup2 interface
  1112.                                 IHXGroup2* pGroup2 = NULL;
  1113.                                 pGroup->QueryInterface(IID_IHXGroup2, (void**) &pGroup2);
  1114.                                 if (pGroup2)
  1115.                                 {
  1116.                                     // Add the track
  1117.                                     pGroup2->AddTrack2(pValues, pReqHeaders);
  1118.                                 }
  1119.                                 HX_RELEASE(pGroup2);
  1120.                             }
  1121.                             HX_RELEASE(pGroup);
  1122.                         }
  1123.                         HX_RELEASE(pReqHeaders);
  1124.                     }
  1125.                     HX_RELEASE(pValues);
  1126.                 }
  1127.             }
  1128.             HX_RELEASE(pMgr);
  1129.         }
  1130.     }
  1131. #endif /* #if defined(HELIX_FEATURE_SMIL2_BRUSH) */
  1132.     return retVal;
  1133. }
  1134. HX_RESULT
  1135. CSmilDocumentRenderer::handleElements()
  1136. {
  1137.     HX_RESULT rc = HXR_OK;
  1138.     if(m_pSmilParser)
  1139.     {
  1140. //if(m_ulParseResult != HXR_STREAM_DONE)
  1141. //{
  1142.     while(HXR_OK == rc)
  1143.     {
  1144. rc = m_pSmilParser->handleNextElement(this);
  1145.     }
  1146.     m_ulParseResult = rc;
  1147. //}
  1148.     }
  1149.     return HXR_OK;
  1150. }
  1151. HX_RESULT CSmilDocumentRenderer::postParseSetup()
  1152. {
  1153.     HX_RESULT retVal = HXR_OK;
  1154.     // There are several things we cannot setup until
  1155.     // we have received all of the CSmilElement's handleElement()
  1156.     // methods up front.
  1157.     //
  1158.     // The first is that we want to set the SiteNeverBlts property
  1159.     // of the site, but in order to do that, we need to know all
  1160.     // the sources and all the animate elements.
  1161.     if (m_pRegionMap)
  1162.     {
  1163.         // Run through the map
  1164.         POSITION pos = m_pRegionMap->GetStartPosition();
  1165.         while (pos)
  1166.         {
  1167.             const char* pszKey = NULL;
  1168.             void*       pVal   = NULL;
  1169.             m_pRegionMap->GetNextAssoc(pos, pszKey, pVal);
  1170.             if (pVal)
  1171.             {
  1172.                 // Get the region pointer
  1173.                 CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pVal;
  1174.                 // Check if this region's site should
  1175.                 // have its SiteNeverBlts property set to "1".
  1176.                 // It should if:
  1177.                 // a) the backgroundColor is transparent
  1178.                 // b) backgroundColor is never animated
  1179.                 // c) backgroundColor is never overridden in a source
  1180.                 if (isTransparent(pRegion->m_ulBackgroundColor) &&
  1181.                     !isAttributeAnimated((const char*) pRegion->m_region,
  1182.                                          kAttrNameBackgroundColor) &&
  1183.                     !isRegionBackgroundColorOverridden(pRegion))
  1184.                 {
  1185.                     setSiteProperty(pRegion->m_pSite, "SiteNeverBlts", "1");
  1186.                 }
  1187.             }
  1188.         }
  1189.     }
  1190.     return retVal;
  1191. }
  1192. HX_RESULT
  1193. CSmilDocumentRenderer::parseDimension(const char* pDimensionString,
  1194.       REF(UINT32) ulValue,
  1195.       REF(BOOL) bIsPercent)
  1196. {
  1197.     HX_RESULT rc = HXR_OK;
  1198.     if(!pDimensionString || strlen(pDimensionString) == 0)
  1199.     {
  1200. ulValue = 0L;
  1201. //[SMIL 1.0 compliance] Helps fix PR 16542.  The caller of this
  1202. // function should look at this return value to determine whether
  1203. // or not the string was empty (and thus 0 is returned in ulValue) or
  1204. // whether "0" or "0%" IS the string (and thus 0 is returned in
  1205. // ulValue along with HXR_OK):
  1206. rc = HXR_FAIL;
  1207.     }
  1208.     else
  1209.     {
  1210. char* pEndPtr = 0;
  1211. ulValue = (UINT32)strtod(pDimensionString, &pEndPtr);
  1212. if(pEndPtr && strcmp(pEndPtr, "%") == 0)
  1213. {
  1214.     bIsPercent = TRUE;
  1215. }
  1216. else
  1217. {
  1218.     bIsPercent = FALSE;
  1219. }
  1220.     }
  1221.     return rc;
  1222. }
  1223. HX_RESULT CSmilDocumentRenderer::computeBoxDimension(CSmilBasicBox* pBox,
  1224.                                                      BoxDimension   eDim)
  1225. {
  1226.     HX_RESULT retVal = HXR_OK;
  1227.     if (pBox)
  1228.     {
  1229.         // Clear the flag that says whether or
  1230.         // not to compute our dimension based on
  1231.         // our children
  1232.         BOOL bPostResolve = FALSE;
  1233.         // Have we already resolved our dimension?
  1234.         if (!pBox->isResolved(eDim))
  1235.         {
  1236.             // We have NOT resolved our dimension yet,
  1237.             // so we need to attempt to resolve it
  1238.             HX_RESULT rv = pBox->computeDimension(eDim);
  1239.             if (FAILED(rv))
  1240.             {
  1241.                 // We could not resolve our dimension
  1242.                 // so we will have to try and resolve it
  1243.                 // from our children.
  1244.                 bPostResolve = TRUE;
  1245.             }
  1246.         }
  1247.         if (pBox->m_pChildList)
  1248.         {
  1249.             // Now we run through our children, computing
  1250.             // their dimensions
  1251.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  1252.             while (pos && SUCCEEDED(retVal))
  1253.             {
  1254.                 CSmilBasicBox* pListBox = (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  1255.                 if (pListBox)
  1256.                 {
  1257.                     retVal = computeBoxDimension(pListBox, eDim);
  1258.                 }
  1259.             }
  1260.             if (SUCCEEDED(retVal) && bPostResolve)
  1261.             {
  1262.                 retVal = pBox->resolveFromChildren(eDim);
  1263.             }
  1264.         }
  1265.     }
  1266.     return retVal;
  1267. }
  1268. void CSmilDocumentRenderer::clearResolvedFlags(CSmilBasicBox* pBox)
  1269. {
  1270.     if (pBox)
  1271.     {
  1272.         // Clear the flags for this box
  1273.         pBox->m_bWidthResolved  = FALSE;
  1274.         pBox->m_bHeightResolved = FALSE;
  1275.         // Recurse through the children
  1276.         if (pBox->m_pChildList)
  1277.         {
  1278.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  1279.             while (pos)
  1280.             {
  1281.                 CSmilBasicBox* pListBox =
  1282.                     (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  1283.                 clearResolvedFlags(pListBox);
  1284.             }
  1285.         }
  1286.     }
  1287. }
  1288. void CSmilDocumentRenderer::resetSites(CSmilBasicBox* pBox, BOOL bOptimizeRedraws)
  1289. {
  1290.     if (pBox)
  1291.     {
  1292.         IHXSite* pSite     = pBox->m_pSite;
  1293.         BOOL      bIsRegion = FALSE;
  1294.         if (pBox->m_pParent)
  1295.         {
  1296.             // This box has a parent, so it has to be a region
  1297.             bIsRegion = TRUE;
  1298.         }
  1299.         if (pSite)
  1300.         {
  1301.             // Get the current position of the site
  1302.             HXxPoint cPos = {0, 0};
  1303.             pSite->GetPosition(cPos);
  1304.             // Set the new position of the site
  1305.             HXxPoint cNewPos = {pBox->m_Rect.left, pBox->m_Rect.top};
  1306. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  1307. #if defined(XXXMEH_DO_VIEWPORT_TLC) && defined(_WINDOWS)
  1308.             if (pBox->m_pParent && !pBox->m_pParent->m_pParent)
  1309.             {
  1310.                 // This has to be a region, so cast
  1311.                 CSmilBasicRegion* pReg = (CSmilBasicRegion*) pBox;
  1312.                 if (!pReg->m_bUnderRootLayout)
  1313.                 {
  1314.                     cNewPos.x += GetSystemMetrics(SM_CXFIXEDFRAME);
  1315.                     cNewPos.y += GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
  1316.                 }
  1317.             }
  1318. #endif
  1319. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  1320.             // If the new position is different from
  1321.             // the old position, then reset the position
  1322.             if (cPos.x != cNewPos.x ||
  1323.                 cPos.y != cNewPos.y)
  1324.             {
  1325.                 if (bIsRegion)
  1326.                 {
  1327.                     CSmilBasicRegion* pReg = (CSmilBasicRegion*) pBox;
  1328.                     MLOG_LAYOUT(m_pErrorMessages,
  1329.                                 "CSmilDocumentRenderer::resetSites() region=%s site->SetPosition(%ld,%ld)n",
  1330.                                 (const char*) pReg->m_region, cNewPos.x, cNewPos.y);
  1331.                 }
  1332.                 pSite->SetPosition(cNewPos);
  1333.                 // Optimize out any site redraws if necessary
  1334.                 if (bOptimizeRedraws)
  1335.                 {
  1336.                     // If we are calling SetPosition() on this
  1337.                     // site, then the site code will automatically
  1338.                     // force a redraw on this site. Therefore, if
  1339.                     // we were planning on doing a ForceRedraw() on
  1340.                     // this site as a result of some animation, then
  1341.                     // it's no longer necessary
  1342.                     removePendingAnimationRedraw(pSite);
  1343.                 }
  1344.             }
  1345.             // Get the current size of the site
  1346.             HXxSize cSize = {0, 0};
  1347.             pSite->GetSize(cSize);
  1348.             // Set the new size of the site
  1349.             HXxSize cNewSize = {HXxRECT_WIDTH(pBox->m_Rect),
  1350.                                 HXxRECT_HEIGHT(pBox->m_Rect)};
  1351.             // If this is different from the size
  1352.             // of the rect, then resize
  1353.             if (cSize.cx != cNewSize.cx ||
  1354.                 cSize.cy != cNewSize.cy)
  1355.             {
  1356.                 if (bIsRegion)
  1357.                 {
  1358.                     CSmilBasicRegion* pReg = (CSmilBasicRegion*) pBox;
  1359.                     MLOG_LAYOUT(m_pErrorMessages,
  1360.                                 "CSmilDocumentRenderer::resetSites() region=%s site->SetSize(%ld,%ld)n",
  1361.                                 (const char*) pReg->m_region, cNewSize.cx, cNewSize.cy);
  1362.                 }
  1363.                 pSite->SetSize(cNewSize);
  1364.                 // Optimize out any site redraws if necessary
  1365.                 if (bOptimizeRedraws)
  1366.                 {
  1367.                     // If we are calling SetSize() on this
  1368.                     // site, then the site code will automatically
  1369.                     // force a redraw on this site. Therefore, if
  1370.                     // we were planning on doing a ForceRedraw() on
  1371.                     // this site as a result of some animation, then
  1372.                     // it's no longer necessary
  1373.                     removePendingAnimationRedraw(pSite);
  1374.                 }
  1375.                 // If this is a region, then we need to
  1376.                 // resize any renderers which are currently
  1377.                 // playing as well.
  1378.                 if (bIsRegion)
  1379.                 {
  1380.                     CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pBox;
  1381.                     resetRendererSites(pRegion);
  1382.                 }
  1383.             }
  1384.         }
  1385.         // Recurse through the children
  1386.         if (pBox->m_pChildList)
  1387.         {
  1388.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  1389.             while (pos)
  1390.             {
  1391.                 CSmilBasicBox* pListBox =
  1392.                     (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  1393.                 resetSites(pListBox, bOptimizeRedraws);
  1394.             }
  1395.         }
  1396.     }
  1397. }
  1398. void CSmilDocumentRenderer::resizeTopLevelBox(CSmilBasicBox* pBox,
  1399.                                               HXxSize        cOrigSize,
  1400.                                               HXxSize        cSize)
  1401. {
  1402.     // A box is only top-level if it has no parent box
  1403.     if (pBox && !pBox->m_pParent)
  1404.     {
  1405.         // Only resize if the current size is different
  1406.         if (cSize.cx != HXxRECT_WIDTH(pBox->m_Rect) ||
  1407.             cSize.cy != HXxRECT_HEIGHT(pBox->m_Rect))
  1408.         {
  1409.             MLOG_LAYOUT(m_pErrorMessages,
  1410.                         "CSmilDocumentRenderer::resizeTopLevelBox(0x%08x,(%ld,%ld),(%ld,%ld))n",
  1411.                         pBox, cOrigSize.cx, cOrigSize.cy, cSize.cx, cSize.cy);
  1412.             // Clear the resolved flags
  1413.             clearResolvedFlags(pBox);
  1414.             // Normally, we have to resolve a top-level box's
  1415.             // dimensions just like anything else, but top-level
  1416.             // boxes can be explicitly resized by the user by
  1417.             // resizing the window. Therefore, we explicitly
  1418.             // set the rectangle for this top-level box
  1419.             pBox->m_Rect.left   = 0;
  1420.             pBox->m_Rect.top    = 0;
  1421.             if (pBox->m_eResizeBehavior == ResizePercentOnly ||
  1422.                 (pBox->m_eResizeBehavior == ResizeZoom && m_bDoNotZoom))
  1423.             {
  1424.                 // If we are NOT zooming, then we simply use
  1425.                 // the new size. Also, this could be called in
  1426.                 // the case where we are using the media size
  1427.                 // to figure out the root-layout size. In that
  1428.                 // case, we don't zoom either.
  1429.                 pBox->m_Rect.right  = cSize.cx;
  1430.                 pBox->m_Rect.bottom = cSize.cy;
  1431.             }
  1432.             else
  1433.             {
  1434.                 // If we are zooming, then we re-calculate 
  1435.                 // using the original top-level size and then
  1436.                 // scale the whole thing.
  1437.                 pBox->m_Rect.right  = cOrigSize.cx;
  1438.                 pBox->m_Rect.bottom = cOrigSize.cy;
  1439.             }
  1440.             // We force resolution of the top-level site
  1441.             pBox->m_bWidthResolved  = TRUE;
  1442.             pBox->m_bHeightResolved = TRUE;
  1443.             // Compute left and right of the region rects
  1444.             computeBoxDimension(pBox, BoxDimensionWidth);
  1445.             // Compute top and bottom of the region rects
  1446.             computeBoxDimension(pBox, BoxDimensionHeight);
  1447.             // If we have zoom resize behavior, then we need to
  1448.             // compute and set the zoom scale factors and then
  1449.             // scale the rects
  1450.             if (pBox->m_eResizeBehavior == ResizeZoom && !m_bDoNotZoom)
  1451.             {
  1452.                 // Compute the x scale factor
  1453.                 double dScaleX = 1.0;
  1454.                 if (cOrigSize.cx > 0)
  1455.                 {
  1456.                     dScaleX = ((double) cSize.cx) / ((double) cOrigSize.cx);
  1457.                 }
  1458.                 // Compute the y scale factor
  1459.                 double dScaleY = 1.0;
  1460.                 if (cOrigSize.cy > 0)
  1461.                 {
  1462.                     dScaleY = ((double) cSize.cy) / ((double) cOrigSize.cy);
  1463.                 }
  1464.                 // Set all the scale factors
  1465.                 zoomRect(pBox, dScaleX, dScaleY);
  1466.             }
  1467.             // Turn on site composition if it's not already on
  1468.             // We don't want to turn it off if it's already on
  1469.             BOOL bInCompositionMode = isSiteCompositionModeON();
  1470.             if (!bInCompositionMode)
  1471.             {
  1472.                 turnSiteCompositionModeON();
  1473.             }
  1474.             // Lock the composition if necessary
  1475.             BOOL bIsLocked = isSiteCompositionLocked();
  1476.             if (!bIsLocked)
  1477.             {
  1478.                 lockSiteComposition();
  1479.             }
  1480.             // Now run through and adjust the size of the sites
  1481.             resetSites(pBox, FALSE);
  1482.             // Unlock the composition if necessary
  1483.             if (!bIsLocked)
  1484.             {
  1485.                 unlockSiteComposition();
  1486.             }
  1487.             // If we're supposed to turn composition mode off,
  1488.             // then do it now. Otherwise, if we were already
  1489.             // in composition mode, then blt the site composition
  1490.             if (!bInCompositionMode)
  1491.             {
  1492.                 turnSiteCompositionModeOFF();
  1493.             }
  1494.         }
  1495.     }
  1496. }
  1497. void CSmilDocumentRenderer::zoomRect(CSmilBasicBox* pBox,
  1498.                                      double         dScaleX,
  1499.                                      double         dScaleY)
  1500. {
  1501.     if (pBox)
  1502.     {
  1503.         // Set the zoom scale factors for this box
  1504.         pBox->m_dZoomScaleFactorX = dScaleX;
  1505.         pBox->m_dZoomScaleFactorY = dScaleY;
  1506.         // Save off the unscaled rect
  1507.         pBox->m_RectNoZoom = pBox->m_Rect;
  1508.         // Apply these scale factors to the rect (with rounding)
  1509.         // Make sure we don't round the left/right and top/bottom
  1510.         // independently - this can result in spurious width/height
  1511.         // changes, even when the actual floating point scaled width
  1512.         // and height doesn't change.
  1513.         double dWidth       = (double) HXxRECT_WIDTH(pBox->m_Rect);
  1514.         double dHeight      = (double) HXxRECT_HEIGHT(pBox->m_Rect);
  1515.         pBox->m_Rect.left   = (INT32) floor((((double) pBox->m_Rect.left)   * dScaleX) + 0.5);
  1516.         pBox->m_Rect.top    = (INT32) floor((((double) pBox->m_Rect.top)    * dScaleY) + 0.5);
  1517.         INT32 lScaledWidth  = (INT32) floor(dWidth * dScaleX + 0.5);
  1518.         INT32 lScaledHeight = (INT32) floor(dHeight * dScaleY + 0.5);
  1519.         pBox->m_Rect.right  = pBox->m_Rect.left + lScaledWidth;
  1520.         pBox->m_Rect.bottom = pBox->m_Rect.top  + lScaledHeight;
  1521.         // Run through any renderer site children and update
  1522.         // the scale factors of their site watchers
  1523.         if (pBox->m_pChildRendererSiteList &&
  1524.             m_pSiteWatcherMap)
  1525.         {
  1526.             LISTPOSITION pos = pBox->m_pChildRendererSiteList->GetHeadPosition();
  1527.             while (pos)
  1528.             {
  1529.                 IHXSite* pRndSite = (IHXSite*) pBox->m_pChildRendererSiteList->GetNext(pos);
  1530.                 if (pRndSite)
  1531.                 {
  1532.                     // Look up the site watcher in the site watcher map
  1533.                     void* pVoid = NULL;
  1534.                     if (m_pSiteWatcherMap->Lookup((void*) pRndSite, pVoid) && pVoid)
  1535.                     {
  1536.                         CSmilSiteWatcher* pWatcher = (CSmilSiteWatcher*) pVoid;
  1537.                         pWatcher->SetZoomScaleFactors(dScaleX, dScaleY);
  1538.                     }
  1539.                 }
  1540.             }
  1541.         }
  1542.         // Is this a region? If it has a parent, then it 
  1543.         // must be a region
  1544.         if (pBox->m_pParent)
  1545.         {
  1546.             // XXXMEH - these are holdover members which currently
  1547.             // need to be set, but should be taken out soon
  1548.             CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pBox;
  1549.             pRegion->m_rect           = pRegion->m_Rect;
  1550.             pRegion->m_originalRect   = pRegion->m_Rect;
  1551.         }
  1552.         // Recurse through the children
  1553.         if (pBox->m_pChildList)
  1554.         {
  1555.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  1556.             while (pos)
  1557.             {
  1558.                 CSmilBasicBox* pListBox =
  1559.                     (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  1560.                 zoomRect(pListBox, dScaleX, dScaleY);
  1561.             }
  1562.         }
  1563.     }
  1564. }
  1565. void CSmilDocumentRenderer::recomputeBoxLayout(CSmilBasicBox* pBox, BOOL bOptimizeRedraws)
  1566. {
  1567.     if (pBox)
  1568.     {
  1569.         // Clear the resolved flags
  1570.         clearResolvedFlags(pBox);
  1571.         // Compute left and right of the region rects
  1572.         computeBoxDimension(pBox, BoxDimensionWidth);
  1573.         // Compute top and bottom of the region rects
  1574.         computeBoxDimension(pBox, BoxDimensionHeight);
  1575.         // We may currently be zoomed. If so, then
  1576.         // adjust for the zoom
  1577.         if (pBox->m_eResizeBehavior == ResizeZoom && !m_bDoNotZoom &&
  1578.             (pBox->m_dZoomScaleFactorX != 1.0 ||
  1579.              pBox->m_dZoomScaleFactorY != 1.0))
  1580.         {
  1581.             // Set all the scale factors
  1582.             zoomRect(pBox, pBox->m_dZoomScaleFactorX, pBox->m_dZoomScaleFactorY);
  1583.         }
  1584.         // Now run through and adjust the size of the sites
  1585.         resetSites(pBox, bOptimizeRedraws);
  1586.     }
  1587. }
  1588. HX_RESULT
  1589. CSmilDocumentRenderer::handleRegion(CSmilRegion* pElement)
  1590. {
  1591.     HX_RESULT retVal = HXR_OK;
  1592.     if (pElement)
  1593.     {
  1594.         // Create the CSmilBasicRegion element
  1595.         CSmilBasicRegion* pRegion = new CSmilBasicRegion(pElement);
  1596.         if (pRegion)
  1597.         {
  1598.             // Set the parent child relationships
  1599.             retVal = setRegionParentChild(pRegion);
  1600.             if (SUCCEEDED(retVal))
  1601.             {
  1602.                 // Add this region to the map - m_pRegionMap is
  1603.                 // the "owner" of the CSmilBasicRegion, so when it
  1604.                 // goes away, all of the CSmilBasicRegion's go away.
  1605.                 if (m_pRegionMap)
  1606.                 {
  1607.                     m_pRegionMap->SetAt((const char*) pElement->m_pNode->m_id,
  1608.                                         (void*) pRegion);
  1609.                 }
  1610.             }
  1611.         }
  1612.         else
  1613.         {
  1614.             retVal = HXR_OUTOFMEMORY;
  1615.         }
  1616.     }
  1617.     else
  1618.     {
  1619.         retVal = HXR_FAIL;
  1620.     }
  1621.     return retVal;
  1622. }
  1623. HX_RESULT
  1624. CSmilDocumentRenderer::handleRegPoint(CSmilRegPoint* pElement)
  1625. {
  1626.     HX_RESULT retVal = HXR_OK;
  1627.     if (pElement && pElement->m_pNode)
  1628.     {
  1629.         // Does the map already exist
  1630.         if (!m_pRegPointMap)
  1631.         {
  1632.             // Create the map
  1633.             m_pRegPointMap = new CHXMapStringToOb();
  1634.         }
  1635.         if (m_pRegPointMap)
  1636.         {
  1637.             // Add this regPoint to the map
  1638.             m_pRegPointMap->SetAt((const char*) pElement->m_pNode->m_id,
  1639.                                   (void*) pElement);
  1640.         }
  1641.         else
  1642.         {
  1643.             retVal = HXR_OUTOFMEMORY;
  1644.         }
  1645.     }
  1646.     else
  1647.     {
  1648.         retVal = HXR_FAIL;
  1649.     }
  1650.     return retVal;
  1651. }
  1652. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  1653. HX_RESULT
  1654. CSmilDocumentRenderer::handleViewport(CSmilViewport* pElement)
  1655. {
  1656.     HX_RESULT retVal = HXR_FAIL;
  1657.     if (pElement)
  1658.     {
  1659.         // Does the viewport list exist yet?
  1660.         if (!m_pViewportList)
  1661.         {
  1662.             // Create the list
  1663.             m_pViewportList = new CHXSimpleList();
  1664.         }
  1665.         if (m_pViewportList)
  1666.         {
  1667.             // Create a viewport object
  1668.             CSmilBasicViewport* pPort = new CSmilBasicViewport(pElement);
  1669.             if (pPort)
  1670.             {
  1671.                 // Add it to the list
  1672.                 m_pViewportList->AddTail((void*) pPort);
  1673.                 // Clear the return value
  1674.                 retVal = HXR_OK;
  1675.             }
  1676.         }
  1677.     }
  1678.     return retVal;
  1679. }
  1680. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  1681. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  1682. HX_RESULT CSmilDocumentRenderer::handleTransition(CSmilTransition* pTrans)
  1683. {
  1684.     HX_RESULT retVal = HXR_FAIL;
  1685.     if (pTrans)
  1686.     {
  1687.         // Create the transition map if necessary
  1688.         if (!m_pTransitionMap)
  1689.         {
  1690.             m_pTransitionMap = new CHXMapStringToOb();
  1691.         }
  1692.         if (m_pTransitionMap)
  1693.         {
  1694.             // Create a transition info object
  1695.             CSmilTransitionInfo* pInfo = new CSmilTransitionInfo(pTrans, m_pContext);
  1696.             if (pInfo)
  1697.             {
  1698.                 // Put this info object in the map
  1699.                 m_pTransitionMap->SetAt((const char*) pTrans->m_pNode->m_id,
  1700.                                         (void*) pInfo);
  1701.                 // Clear the return value
  1702.                 retVal = HXR_OK;
  1703.             }
  1704.         }
  1705.     }
  1706.     return retVal;
  1707. }
  1708. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  1709. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  1710. HX_RESULT CSmilDocumentRenderer::handleAnimate(CSmilAnimateElement* pAnimate)
  1711. {
  1712.     MLOG_ANIM(m_pErrorMessages,"CSmilDocumentRenderer::handleAnimate() id=%s tel=%s t=%lun",
  1713.                 (const char*) pAnimate->m_pNode->m_id,
  1714.                 (const char*) *pAnimate->m_pTargetElementID,
  1715.                 pAnimate->m_ulDelay);
  1716.     HX_RESULT retVal = HXR_OK;
  1717.     if (pAnimate)
  1718.     {
  1719.         // XXXMEH - try here to schedule other animations and
  1720.         // elements that may be using this animate element as
  1721.         // a sync-arc. This should get us through interop, but this
  1722.         // needs to be re-examined later.
  1723.         m_pSmilParser->durationResolved(pAnimate->m_pNode->m_id,
  1724.                                         pAnimate->m_ulActiveDuration);
  1725.         // Add this to the animation map
  1726.         if (!m_pAnimationMap)
  1727.         {
  1728.             m_pAnimationMap = new CHXMapStringToOb();
  1729.         }
  1730.         if (m_pAnimationMap)
  1731.         {
  1732.             m_pAnimationMap->SetAt(pAnimate->m_pNode->m_id, (void*) pAnimate);
  1733.         }
  1734.         // Update the duration contributed to
  1735.         // only by animations
  1736.         UINT32 ulAnimEnd = pAnimate->m_ulDelay + pAnimate->m_ulActiveDuration;
  1737.         if (ulAnimEnd > m_ulAnimDuration)
  1738.         {
  1739.             m_ulAnimDuration = ulAnimEnd;
  1740.         }
  1741.         // See if we've already scheduled an event for
  1742.         // this animate element
  1743.         CSmilAnimateEvent* pAnimEvent = getAnimateEvent(pAnimate);
  1744.         if (pAnimEvent)
  1745.         {
  1746.             // We HAVE already scheduled an event
  1747.             // for this animate element. This is most likely
  1748.             // an interactive animation which can begin
  1749.             // several times. We should adjust the time for
  1750.             // this event instead of adding a new event.
  1751.             //
  1752.             // Remove the event from the queue
  1753.             removeEvent(pAnimEvent);
  1754.             // Update the event time
  1755.             pAnimEvent->m_ulEventTime = pAnimate->m_ulDelay;
  1756.             // Re-insert into the queue with the new time
  1757.             insertEvent(pAnimEvent);
  1758.         }
  1759.         else
  1760.         {
  1761.             // We have NOT already scheduled an event
  1762.             // for this animate element
  1763.             //
  1764.             // Schedule the begin animation event
  1765.             UINT16 usGroupIndexShifted = m_usAnimBaseGroupIndex + pAnimate->m_pNode->m_nGroup;
  1766.             CSmilAnimateEvent* pEvent = new CSmilAnimateEvent(usGroupIndexShifted,
  1767.                                                               pAnimate->m_ulDelay,
  1768.                                                               FALSE,
  1769.                                                               pAnimate,
  1770.                                                               this,
  1771.                                                               m_pSmilParser);
  1772.             if (pEvent)
  1773.             {
  1774.                 // Put the event only the timeline
  1775.                 insertEvent(pEvent);
  1776.             }
  1777.         }
  1778.     }
  1779.     else
  1780.     {
  1781.         retVal = HXR_FAIL;
  1782.     }
  1783.     return retVal;
  1784. }
  1785. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  1786. HX_RESULT CSmilDocumentRenderer::handleRemoveTimeUpdate(CSmilElement* pElement,
  1787.                                                         UINT32        ulRemoveTime)
  1788. {
  1789.     MLOG_EVENT(m_pErrorMessages,
  1790.                "handleRemoveTimeUpdate(0x%08x,%lu)ntmediaID=%snttick=%lun",
  1791.                pElement, ulRemoveTime,
  1792.                (const char*) pElement->m_pNode->m_id,
  1793.                HX_GET_BETTERTICKCOUNT());
  1794.     HX_RESULT retVal = HXR_OK;
  1795.     if (pElement && pElement->m_pNode &&
  1796.         m_pEventList && m_pEventList->GetCount() > 0)
  1797.     {
  1798.         // Search through the event queue to find
  1799.         // the hide event for this element.
  1800.         CHXSimpleList cTmp;
  1801.         const char*   pszID = (const char*) pElement->m_pNode->m_id;
  1802.         LISTPOSITION  pos   = m_pEventList->GetHeadPosition();
  1803.         while (pos)
  1804.         {
  1805.             BOOL              bRemoved   = FALSE;
  1806.             CSmilLayoutEvent* pListEvent = (CSmilLayoutEvent*) m_pEventList->GetAt(pos);
  1807.             if (pListEvent && pListEvent->m_type == CSmilLayoutEvent::eHideSite)
  1808.             {
  1809.                 CSmilShowSiteEvent* pListHide = (CSmilShowSiteEvent*) pListEvent;
  1810.                 if (!strcmp(pszID, pListHide->getMediaID()) &&
  1811.                     pListHide->m_ulEventTime != ulRemoveTime)
  1812.                 {
  1813.                     MLOG_EVENT(m_pErrorMessages,
  1814.                                "tRemoving event from list (%s,%lu,%u,%lu,%lu,%s,%s) tick=%lun",
  1815.                                pListHide->getEventTypeName(),
  1816.                                pListHide->m_ulEventTime,
  1817.                                pListHide->m_uGroupIndex,
  1818.                                pListHide->m_bOnlyHideSite,
  1819.                                pListHide->m_bIgnorEvent,
  1820.                                pListHide->getMediaID(),
  1821.                                pListHide->getRegionID(),
  1822.                                HX_GET_BETTERTICKCOUNT());
  1823.                     // Remove the event from the list
  1824.                     pos = m_pEventList->RemoveAt(pos);
  1825.                     // Set the flag
  1826.                     bRemoved = TRUE;
  1827.                     // Save onto the temporary list
  1828.                     cTmp.AddTail((void*) pListHide);
  1829.                 }
  1830.             }
  1831.             if (!bRemoved)
  1832.             {
  1833.                 m_pEventList->GetNext(pos);
  1834.             }
  1835.         }
  1836.         // Did we remove any events?
  1837.         if (cTmp.GetCount() > 0)
  1838.         {
  1839.             // Loop through the removed events
  1840.             pos = cTmp.GetHeadPosition();
  1841.             while (pos)
  1842.             {
  1843.                 CSmilShowSiteEvent* pHideEvent = (CSmilShowSiteEvent*) cTmp.GetNext(pos);
  1844.                 if (pHideEvent)
  1845.                 {
  1846.                     // Set the new event time
  1847.                     pHideEvent->m_ulEventTime = ulRemoveTime;
  1848.                     // Get the this event's group duration
  1849.                     UINT32 ulGroupDur = 0;
  1850.                     if (getGroupDuration(pHideEvent->m_uGroupIndex, ulGroupDur))
  1851.                     {
  1852.                         // Does this media have fill="remove"?
  1853.                         FillType eFill = getMediaFillBehavior((const char*) pHideEvent->getMediaID());
  1854.                         // We got the group duration.
  1855.                         // Is our new hide time scheduled for the
  1856.                         // group duration?
  1857.                         if (pHideEvent->m_ulEventTime == ulGroupDur &&
  1858.                             eFill                     != FillRemove)
  1859.                         {
  1860.                             // Yes, it is, so set the flag that
  1861.                             // says to ignore the hide
  1862.                             pHideEvent->m_bIgnorEvent = TRUE;
  1863.                         }
  1864.                         else
  1865.                         {
  1866.                             // No, the hide is NOT scheduled for the group
  1867.                             // duration, so clear the flag that
  1868.                             // says to ignore the hide
  1869.                             pHideEvent->m_bIgnorEvent = FALSE;
  1870.                         }
  1871.                     }
  1872.                     // Re-insert into the event queue
  1873.                     MLOG_EVENT(m_pErrorMessages,
  1874.                                "tInserting event into list (%s,%lu,%u,%lu,%lu,%s,%s) tick=%lun",
  1875.                                pHideEvent->getEventTypeName(),
  1876.                                pHideEvent->m_ulEventTime,
  1877.                                pHideEvent->m_uGroupIndex,
  1878.                                pHideEvent->m_bOnlyHideSite,
  1879.                                pHideEvent->m_bIgnorEvent,
  1880.                                pHideEvent->getMediaID(),
  1881.                                pHideEvent->getRegionID(),
  1882.                                HX_GET_BETTERTICKCOUNT());
  1883.                     insertEvent(pHideEvent);
  1884.                 }
  1885.             }
  1886.         }
  1887.     }
  1888.     else
  1889.     {
  1890.         retVal = HXR_FAIL;
  1891.     }
  1892.     return retVal;
  1893. }
  1894. HX_RESULT CSmilDocumentRenderer::handleExternalMediaMarkerFile(CSmilElement* pElement,
  1895.                                                                const char*   pszID,
  1896.                                                                const char*   pszExternalFileName,
  1897.                                                                const char*   pszRelativeSource)
  1898. {
  1899.     HX_RESULT retVal = HXR_OK;
  1900.     if (pElement && pszID && pszExternalFileName && pszRelativeSource)
  1901.     {
  1902.         // First convert the URL of the source
  1903.         CHXString cSrc;
  1904.         convertURL((const char*) m_pParent->getURLRoot(),
  1905.                    (const char*) m_pParent->getURLPrefix(),
  1906.                    (const char*) pszRelativeSource,
  1907.                    cSrc);
  1908.         // Now generate a new root and prefix
  1909.         CHXString cNewPrefix;
  1910.         CHXString cNewRoot;
  1911.         char*     pszNewFrag = NULL;
  1912.         CHXURL::GeneratePrefixRootFragment((const char*) cSrc,
  1913.                                            cNewPrefix, 
  1914.                                            cNewRoot,
  1915.                                            pszNewFrag);
  1916.         HX_VECTOR_DELETE(pszNewFrag);
  1917.         // Now make the external media marker file name
  1918.         // relative to the source
  1919.         CHXString cExtFile;
  1920.         convertURL((const char*) cNewRoot,
  1921.                    (const char*) cNewPrefix,
  1922.                    pszExternalFileName,
  1923.                    cExtFile);
  1924.         // Now check to see if we have already done a TrackAdded for
  1925.         // this external media marker file name
  1926.         CExternalMediaMarkerInfo* pInfo = getExternalMediaMarkerInfo(cExtFile);
  1927.         if (!pInfo)
  1928.         {
  1929.             // This file is not already present
  1930.             // Create a ExternalMediaMarkerInfo struct
  1931.             pInfo = new CExternalMediaMarkerInfo();
  1932.             if (pInfo)
  1933.             {
  1934.                 // Create the list
  1935.                 pInfo->m_pIDList = new CHXSimpleList();
  1936.                 if (pInfo->m_pIDList)
  1937.                 {
  1938.                     // Add the id
  1939.                     char* pID = new char [strlen(pszID) + 1];
  1940.                     if (pID)
  1941.                     {
  1942.                         // Copy the string
  1943.                         strcpy(pID, pszID); /* Flawfinder: ignore */
  1944.                         // Add this id to the list
  1945.                         pInfo->m_pIDList->AddTail((void*) pID);
  1946.                         // Create the string
  1947.                         pInfo->m_pszAddTrackURL = new char [cExtFile.GetLength() + 1];
  1948.                         if (pInfo->m_pszAddTrackURL)
  1949.                         {
  1950.                             // Copy the string
  1951.                             strcpy(pInfo->m_pszAddTrackURL, (const char*) cExtFile); /* Flawfinder: ignore */
  1952.                             // Add this info to the list
  1953.                             if (!m_pExternalMediaMarkerList)
  1954.                             {
  1955.                                 m_pExternalMediaMarkerList = new CHXSimpleList();
  1956.                             }
  1957.                             if (m_pExternalMediaMarkerList)
  1958.                             {
  1959.                                 m_pExternalMediaMarkerList->AddTail((void*) pInfo);
  1960.                             }
  1961.                             // Create an IHXValues
  1962.                             IHXCommonClassFactory* pFact   = m_pParent->getFactory();
  1963.                             IHXValues*             pValues = NULL;
  1964.                             retVal = pFact->CreateInstance(CLSID_IHXValues, (void**) &pValues);
  1965.                             if (SUCCEEDED(retVal))
  1966.                             {
  1967.                                 // Set the persistent component ID
  1968.                                 pValues->SetPropertyULONG32("PersistentComponentID", m_ulPersistentComponentID);
  1969.                                 // Set the URL
  1970.                                 setProperty(pValues, "url", cExtFile);
  1971.                                 // Set a flag saying this is an external media marker
  1972.                                 setProperty(pValues, "ExternalMarkerFile", "1");
  1973.                                 // We don't really have an id for this, but we 
  1974.                                 // will create one from the pointer of the info struct
  1975.                                 char szTmpID[48]; /* Flawfinder: ignore */
  1976.                                 sprintf(szTmpID, "xmmf_0x%08x", pInfo); /* Flawfinder: ignore */
  1977.                                 setProperty(pValues, "id",       (const char*) szTmpID);
  1978.                                 setProperty(pValues, "repeatid", (const char*) szTmpID);
  1979.                                 // XXXMEH - are there any other properties we need to set?
  1980.                                 IHXGroup* pGroup = NULL;
  1981.                                 if (m_pGroupMap &&
  1982.                                     m_pGroupMap->Lookup(pElement->m_pNode->m_nGroup, (void*&) pGroup) &&
  1983.                                     pGroup)
  1984.                                 {
  1985.                                     // Add this external file as a track
  1986.                                     pGroup->AddTrack(pValues);
  1987.                                 }
  1988.                                 else
  1989.                                 {
  1990.                                     retVal = HXR_FAIL;
  1991.                                 }
  1992.                             }
  1993.                             HX_RELEASE(pValues);
  1994.                         }
  1995.                         else
  1996.                         {
  1997.                             retVal = HXR_FAIL;
  1998.                         }
  1999.                     }
  2000.                     else
  2001.                     {
  2002.                         retVal = HXR_FAIL;
  2003.                     }
  2004.                 }
  2005.                 else
  2006.                 {
  2007.                     retVal = HXR_FAIL;
  2008.                 }
  2009.             }
  2010.             else
  2011.             {
  2012.                 retVal = HXR_FAIL;
  2013.             }
  2014.             if (FAILED(retVal))
  2015.             {
  2016.                 HX_DELETE(pInfo);
  2017.             }
  2018.         }
  2019.         else
  2020.         {
  2021.             // We already have done an AddTrack for this file,
  2022.             // so we simply need to add this id to the list,
  2023.             // if it is not already present.
  2024.             if (!isIDMappedToExternalMediaMarkerFile(pInfo, pszID))
  2025.             {
  2026.                 // Add the id
  2027.                 char* pID = new char [strlen(pszID) + 1];
  2028.                 if (pID)
  2029.                 {
  2030.                     // Copy the string
  2031.                     strcpy(pID, pszID); /* Flawfinder: ignore */
  2032.                     // Add this id to the list
  2033.                     pInfo->m_pIDList->AddTail((void*) pID);
  2034.                 }
  2035.             }
  2036.         }
  2037.     }
  2038.     else
  2039.     {
  2040.         retVal = HXR_FAIL;
  2041.     }
  2042.     return retVal;
  2043. }
  2044. HX_RESULT
  2045. CSmilDocumentRenderer::handleRootLayout(CSmilRootLayout* pElement)
  2046. {
  2047.     HX_RESULT retVal = HXR_OK;
  2048.     if (pElement)
  2049.     {
  2050.         // Set the parser root-layout into the object
  2051.         m_pRootLayout->SetParserRootLayout(pElement);
  2052.     }
  2053.     else
  2054.     {
  2055.         retVal = HXR_FAIL;
  2056.     }
  2057.     return retVal;
  2058. }
  2059. HX_RESULT
  2060. CSmilDocumentRenderer::handleAddGroup(CSmilAddGroup* pElement)
  2061. {
  2062.     HX_RESULT rc = HXR_OK;
  2063.     if(!m_pGroupMap)
  2064.     {
  2065. m_pGroupMap = new CHXMapLongToObj;
  2066.     }
  2067.     IHXPlayer* pPlayer = m_pParent->getPlayer();
  2068.     IHXGroupManager* pMgr = 0;
  2069.     if(HXR_OK == pPlayer->QueryInterface(IID_IHXGroupManager, (void**)&pMgr))
  2070.     {
  2071. IHXGroup* pGroup = NULL;
  2072. IHXGroup2* pGroup2 = NULL;
  2073. IHXPrefetch* pPrefetch = NULL;
  2074. if (m_pParent->m_bUseNestedMeta && 0 == m_ulGroupIndex)
  2075. {
  2076.     rc = pMgr->GetCurrentGroup(m_uGroupIndexWithin);
  2077.     rc = pMgr->GetGroup(m_uGroupIndexWithin, pGroup);
  2078. }
  2079. else
  2080. {
  2081.     rc = pMgr->CreateGroup(pGroup);
  2082. }
  2083. if (HXR_OK == rc)
  2084. // release pGroup when m_pGroupMap is destructed
  2085. {
  2086.     CHXHeader* pGroupValues = new CHXHeader;
  2087.     pGroupValues->AddRef();
  2088.     if(pElement->m_ulDuration != (UINT32)-1)
  2089.     {
  2090. pGroupValues->SetPropertyULONG32("duration", pElement->m_ulDuration);
  2091.     }
  2092.     pGroupValues->SetPropertyULONG32("total_tracks", pElement->m_nTotalTracks);
  2093.     pGroupValues->SetPropertyULONG32("initial_tracks", pElement->m_nInitTracks);
  2094.     
  2095.     pGroupValues->SetPropertyULONG32("PersistentComponentID", m_ulPersistentComponentID);
  2096.     // copy all the node values to group values
  2097.     IHXValues* pValues = pElement->m_pValues;
  2098.     if(pValues)
  2099.     {
  2100. IHXBuffer* pBuf = NULL;
  2101. const char* pName = NULL;
  2102. HX_RESULT res = 
  2103.     pValues->GetFirstPropertyCString(pName, pBuf);
  2104. while(HXR_OK == res)
  2105. {
  2106.     pGroupValues->SetPropertyCString(pName, pBuf);
  2107.     HX_RELEASE(pBuf);
  2108.     res = pValues->GetNextPropertyCString(pName, pBuf);
  2109. }
  2110.     }
  2111.     
  2112.     pGroup->SetGroupProperties(pGroupValues);    
  2113.     if (HXR_OK == pGroup->QueryInterface(IID_IHXGroup2, (void**)&pGroup2))
  2114.     {
  2115. pGroup2->SetPersistentComponentProperties(m_ulPersistentComponentID,
  2116.   pGroupValues);
  2117.     }
  2118.     HX_RELEASE(pGroupValues);
  2119.     if (m_pParent->m_bUseNestedMeta && 0 == m_ulGroupIndex)
  2120.     {
  2121. GroupAdded(m_uGroupIndexWithin, pGroup);
  2122.     }
  2123.     else
  2124.     {
  2125. pMgr->AddGroup(pGroup);
  2126.     }
  2127.     
  2128.     m_ulTrackIndex = 0;
  2129.     m_ulGroupIndex++;
  2130.     (*m_pGroupMap)[pElement->m_nGroup] = pGroup;
  2131.     if (HXR_OK == pGroup->QueryInterface(IID_IHXPrefetch, (void**)&pPrefetch))
  2132.     {
  2133.                 // Add ourselves as a prefetch sink
  2134. pPrefetch->AddPrefetchSink(this);
  2135.                 // Add ourselves as a track sink
  2136.                 IHXTrackSink* pSink = NULL;
  2137.                 QueryInterface(IID_IHXTrackSink, (void**) &pSink);
  2138.                 if (pSink)
  2139.                 {
  2140.                     // XXXMEH - where is the right place to remove
  2141.                     // ourselves as a track sink?
  2142.                     pGroup2->AddTrackSink(pSink);
  2143.                 }
  2144.                 HX_RELEASE(pSink);
  2145.     }
  2146.     HX_RELEASE(pPrefetch);
  2147.     HX_RELEASE(pGroup2);
  2148. }
  2149.     }
  2150.     HX_RELEASE(pMgr);
  2151.     return rc;
  2152. }
  2153. HX_RESULT
  2154. CSmilDocumentRenderer::GetCurGroupDuration(REF(UINT32) ulCurGrpDur)
  2155. {
  2156.     HX_RESULT pnrslt = HXR_OK;
  2157.     ulCurGrpDur = m_ulCurGroupDuration;
  2158.     return pnrslt;
  2159. }
  2160. // /This is needed for fixing PR 56686 (and others) where the presentation
  2161. // duration is not high enough to account for time-container-extended
  2162. // duration.  E.g.,
  2163. //   <body><par><img dur="1s"/><excl dur="20s"></excl></par></body>
  2164. // should play for 20s even though the excl is empty, but the core didn't
  2165. // used to have any way of knowing about this since only media durations
  2166. // are made know to the core (via addTrack()).  The below method bumps up
  2167. // the presentation duration if a higher-than-m_ulCurGroupDuration value
  2168. // is declared by the outer time container (body child):
  2169. // /Also, made it so we *always* set this duration, even if we decide it
  2170. // is lower (see below):
  2171. HX_RESULT
  2172. CSmilDocumentRenderer::resolveGroupDurToOuterTimeContainerDur(
  2173. UINT32 ulGroupIndex, UINT32 ulGroupTimeContainerDuration)
  2174. {
  2175. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUGOUT_RESOLVEGROUPDUR)
  2176. {
  2177. FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
  2178. ::fprintf(f1, "CSmilDocumentRenderer::resolveGroupDurToOuterTimeContainerDur"
  2179. "(group=%lu, groupTimeContainerDur=%lu), m_ulCurGroupDuration=%lu%sn",
  2180. ulGroupIndex, ulGroupTimeContainerDuration, m_ulCurGroupDuration,
  2181. m_pGroupInfoMap!=NULL?"":", (skipped: m_pGroupInfoMap is NULL)");
  2182. ::fclose(f1);
  2183. }
  2184. #endif
  2185.     HX_RESULT pnrslt = HXR_OK;
  2186.     SMILGroupInfo* pGroupInfo = NULL;
  2187.     if (m_pGroupInfoMap  &&  // /Check for NULL fixes PR 65874.
  2188.     m_pGroupInfoMap->Lookup(ulGroupIndex, (void*&)pGroupInfo))
  2189.     {
  2190. // /Changed '>' to '>=' to fix "PR55117-related_andPR6XXX5...": re-
  2191. // force core to adjust presentation duration after all media has
  2192. // been added:
  2193. // /For PR59584+,  we *always* set this duration, even if we decide it
  2194. // is lower, because we may reset the last track's duration to something
  2195. // less and the core will then adjust without accounting for the frozen
  2196. // period that that track may need, e.g., if last-in-seq is a par w/discrete
  2197. // image in it, the core will first think it's 5sec long, but we reset its
  2198. // duration to be .001sec and freeze it for the remainder of its par
  2199. // parent (that has an explicit dur or end): removed if():
  2200. #if defined(XXXEH_ONLY_SET_IF_SAME_OR_HIGHER_20011024)
  2201. if (ulGroupTimeContainerDuration >=
  2202. // /Changing this from pGroupInfo->m_ulDuration to
  2203. // m_ulCurGroupDuration fixes PR 56686:
  2204. m_ulCurGroupDuration // /was:  pGroupInfo->m_ulDuration)
  2205. // /Helps fix PR 62688; group duration is now resolved to
  2206. // non-indefinite time, so let's update group duration:
  2207. ||  (WAY_IN_THE_FUTURE <= m_ulCurGroupDuration  &&
  2208. WAY_IN_THE_FUTURE > ulGroupTimeContainerDuration) )
  2209. #endif
  2210. {
  2211.     if (ulGroupTimeContainerDuration > WAY_IN_THE_FUTURE)
  2212.     {
  2213. ulGroupTimeContainerDuration = WAY_IN_THE_FUTURE;
  2214.     }
  2215.     // duration is the end of group
  2216.     pGroupInfo->m_ulDuration = ulGroupTimeContainerDuration;
  2217.     pGroupInfo->m_bDurationSet = TRUE;
  2218.     ignoreLastHideEvent(ulGroupIndex, pGroupInfo);
  2219.     // /Update the "persistent layout stream" duration
  2220.     if (m_pPersistentLayoutStream)
  2221.     {
  2222. IHXValues* pStreamProps = NULL;
  2223. m_pPersistentLayoutStream->GetProperties(pStreamProps);
  2224. if (pStreamProps)
  2225. {
  2226.     pStreamProps->SetPropertyULONG32("duration",
  2227.     ulGroupTimeContainerDuration);
  2228.     m_pPersistentLayoutStream->SetProperties(pStreamProps);
  2229.                     // /The following if()-block fixes PR 108178: the core will
  2230.                     // ignore the layoutstream duration property if we've
  2231.                     // ever given the group a duration property even if it was
  2232.                     // the flag-it-as-unresolved WAY_IN_THE_FUTURE value.
  2233.                     // So, we need to reset the group duration property if
  2234.                     // it's been set to some other value:
  2235.                     IHXPlayer* pPlayer = m_pParent->getPlayer();
  2236.                     IHXGroupManager* pMgr = 0;
  2237.                     if (HXR_OK == pPlayer->QueryInterface(IID_IHXGroupManager,
  2238.                              (void**)&pMgr))
  2239.                     {
  2240.                         IHXGroup* pGroup = NULL;
  2241.                         IHXGroup2* pGroup2 = NULL;
  2242.                         if (HXR_OK == pMgr->GetGroup(ulGroupIndex, pGroup) &&
  2243.                                 HXR_OK == pGroup->QueryInterface(IID_IHXGroup2,
  2244.                                 (void**)&pGroup2))
  2245.                         {
  2246.                             IHXValues* pGroupProperties = NULL;
  2247.                             pGroup2->GetPersistentComponentProperties(
  2248.                                   m_ulPersistentComponentID, pGroupProperties);
  2249.                             if(pGroupProperties)
  2250.                             {
  2251.                                 UINT32 ulPrevGroupDur = 0;
  2252.                                 if (HXR_OK ==
  2253.                                         pGroupProperties->GetPropertyULONG32("duration",
  2254.                                         ulPrevGroupDur)   &&  ulPrevGroupDur !=
  2255.                                         ulGroupTimeContainerDuration)
  2256.                                 {
  2257.                                     pGroupProperties->SetPropertyULONG32("duration",
  2258.                                             ulGroupTimeContainerDuration);
  2259.                                 }
  2260.                             }
  2261.                             HX_RELEASE(pGroupProperties);
  2262.                         }
  2263.                         HX_RELEASE(pGroup2);
  2264.                         HX_RELEASE(pGroup);
  2265.                     }
  2266.                     HX_RELEASE(pMgr);
  2267.                 }
  2268. HX_RELEASE(pStreamProps);
  2269.     }
  2270.     PersistentDurationSet(pGroupInfo->m_ulDuration,
  2271.     m_pSmilParser->m_ulPersistentComponentDelay,
  2272.     // /XXXEH- TODO: check w/Henry if this is OK:
  2273.     FALSE);
  2274. }
  2275.     }
  2276.     else
  2277.     {
  2278. pnrslt = HXR_UNEXPECTED;
  2279.     }
  2280.     return pnrslt;
  2281. }
  2282. void
  2283. CSmilDocumentRenderer::setProperty(IHXValues* pValues, 
  2284.     const char* pName, const char* pValue)
  2285. {
  2286.     IHXBuffer* pBuf = 0;
  2287.     IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  2288.     if(HXR_OK == pFactory->CreateInstance(CLSID_IHXBuffer,
  2289.          (void**)&pBuf))
  2290.     {
  2291. pBuf->Set((BYTE*)pValue, strlen(pValue)+1);
  2292. pValues->SetPropertyCString(pName, pBuf);
  2293. pBuf->Release();
  2294.     }
  2295. }
  2296. HX_RESULT CSmilDocumentRenderer::convertURL(const char* pszBaseRoot, const char* pszBasePrefix,
  2297.                                             const char* pURL, CHXString& newURL)
  2298. {
  2299.     HX_RESULT retVal = HXR_OK;
  2300.     CHXURL urlObj(pURL);
  2301.     IHXValues* pHeader = urlObj.GetProperties();
  2302.     if (pHeader)
  2303.     {
  2304.         IHXBuffer* pBuffer = NULL;
  2305.         HX_RESULT   rc      = pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer);
  2306.         if (SUCCEEDED(rc))
  2307.         {
  2308.     // fully qualified URL
  2309.     newURL = pURL;
  2310.         }
  2311.         else
  2312.         {
  2313.     // relative URL
  2314.     // if it starts with '/', make it relative to the root of 
  2315.     // the URL prefix
  2316.     if(*pURL == '/')
  2317.     {
  2318.                 newURL = pszBaseRoot;
  2319.                 newURL += pURL;
  2320.     }
  2321.     else if (strnicmp(pURL, URL_COMMAND, sizeof(URL_COMMAND) - 1) == 0)
  2322.     {
  2323.         newURL = pURL;
  2324.     }
  2325.     else
  2326.     {
  2327.                 newURL = pszBasePrefix;
  2328.                 newURL += pURL;
  2329.     }
  2330.         }
  2331.         HX_RELEASE(pBuffer);
  2332.         HX_RELEASE(pHeader);
  2333.     }
  2334.     else
  2335.     {
  2336.         retVal = HXR_FAIL;
  2337.     }
  2338.     return retVal;
  2339. }
  2340. HX_RESULT CSmilDocumentRenderer::handleSource(CSmilSource* pElement)
  2341. {
  2342.     MLOG_SRC(m_pErrorMessages,"handleSource() id=%s del=%lu dur=%lu m_ulCurrentTime=%lun",
  2343.              (const char*) pElement->m_pNode->m_id,
  2344.              pElement->m_ulDelay,
  2345.              pElement->m_ulDuration,
  2346.              m_ulCurrentTime);
  2347.     HX_RESULT rc = HXR_OK;
  2348.     CHXString urlString;
  2349.     convertURL((const char*) m_pParent->getURLRoot(),
  2350.                (const char*) m_pParent->getURLPrefix(),
  2351.                (const char*) pElement->m_src,
  2352.                urlString);
  2353.     BOOL bIsPrefetchElement = (pElement->m_pNode  &&
  2354.     SMILPrefetch == pElement->m_pNode->m_tag);
  2355.     BOOL bDurationPropSet = FALSE;
  2356.     double fDur = -1;
  2357. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUG_HANDLESOURCE_AND_TRACKDURATIONSET)
  2358. {FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
  2359. ::fprintf(f1, "handleSource(media id=%s, duration=%lu, delay=%lu%s, maxDuration=%lu, clipBegin=%lu)n",
  2360.  (const char*)pElement->m_pNode->m_id, pElement->m_ulDuration,pElement->m_ulDelay,
  2361.  WAY_IN_THE_FUTURE==pElement->m_ulDelay?"(UNRESOLVED)":"", pElement->m_ulMaxDuration, pElement->m_ulClipBegin);::fclose(f1);}
  2362. #endif
  2363.     IHXGroup* pGroup = 0;
  2364.     HX_ASSERT(WAY_IN_THE_FUTURE > pElement->m_ulDelay);
  2365.     // /For PR 59584: don't add a track whose begin is indefinite:
  2366.     if (WAY_IN_THE_FUTURE <= pElement->m_ulDelay)
  2367.     {
  2368. goto cleanup;
  2369.     }
  2370.     if(m_pGroupMap &&  pElement->m_pNode  &&
  2371.        m_pGroupMap->Lookup(pElement->m_pNode->m_nGroup, (void*&)pGroup))
  2372.     {
  2373. IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  2374. IHXValues* pValues = 0;
  2375. if(HXR_OK == pFactory->CreateInstance(CLSID_IHXValues,
  2376. (void**)&pValues))
  2377. {
  2378.     pValues->SetPropertyULONG32("PersistentComponentID", m_ulPersistentComponentID);    
  2379.     setProperty(pValues, "url", urlString);
  2380.     setProperty(pValues, "id", pElement->m_pNode->m_id);
  2381.     setProperty(pValues, "repeatid", pElement->m_pNode->m_repeatid);
  2382.     if (!bIsPrefetchElement)
  2383.     {
  2384. setProperty(pValues, "playto", pElement->m_region);
  2385. if(pElement->m_region.GetLength() > 0)
  2386. {
  2387.     // save original region name in track values
  2388.     setProperty(pValues, "region", pElement->m_region);
  2389. }
  2390.                 // Set the fill string. We should get it from pElement->m_eActualFill,
  2391.                 // since this is the value which takes fillDefault into account.
  2392.                 
  2393. // XXX HP set "fill" as ULONG32 is much efficient than string!!
  2394. //        no convertion needed
  2395. CHXString cFill;
  2396.                 CSmilParser::getFillString(pElement->m_eActualFill, cFill);
  2397. setProperty(pValues, "fill", cFill);
  2398. pValues->SetPropertyULONG32("fill", pElement->m_eActualFill);
  2399.                 CHXString cErase;
  2400.                 CSmilParser::getEraseString(pElement->m_eErase, cErase);
  2401.                 setProperty(pValues, "erase", cErase);
  2402.                 if (pElement->m_beginTransition.GetLength() > 0)
  2403.                 {
  2404.                     setProperty(pValues, "beginTransition", pElement->m_beginTransition);
  2405.                 }
  2406.                 if (pElement->m_endTransition.GetLength() > 0)
  2407.                 {
  2408.                     setProperty(pValues, "endTransition", pElement->m_endTransition);
  2409.                 }
  2410.     }
  2411.     setProperty(pValues, "track-hint",
  2412. pElement->m_pNode->m_trackHint);
  2413.     pValues->SetPropertyULONG32("lexicalNum", pElement->m_pNode->m_ulTagStartLine);
  2414.             // Check the rn:accessErrorBehavior property of this element
  2415.             AccessErrorBehavior eErr =
  2416.                 m_pSmilParser->getAccessErrorBehavior(pElement->m_pNode);
  2417.             if (eErr == AccessErrorBehaviorContinue)
  2418.             {
  2419.                 // Set the property
  2420.                 setProperty(pValues, "accessErrorBehavior", "continue");
  2421.                 // Since we have rn:accessErrorBehavior="continue" behavior,
  2422.                 // then we need to provide an alternative URL. We want a
  2423.                 // broken window to show up. Since the GIF renderer has this
  2424.                 // ability, then we will simply provide a corrupt inline GIF.
  2425.                 setProperty(pValues, "altURL",
  2426.                             "data:image/gif,any_non_gif_junk");
  2427.             }
  2428.             else
  2429.             {
  2430.                 // Set the property
  2431.                 setProperty(pValues, "accessErrorBehavior", "stop");
  2432.             }
  2433.     UINT32 ulDelay = 0;
  2434.     if(pElement->m_ulDelay != (UINT32)-1)
  2435.     {
  2436. pValues->SetPropertyULONG32("delay", pElement->m_ulDelay);
  2437. ulDelay = pElement->m_ulDelay;
  2438.     }
  2439.     ULONG32 ulDurationUsedInProperties = (UINT32)-1;
  2440.     if(pElement->m_ulDuration != (UINT32)-1  &&
  2441.     // /We don't want to use explicitly-set duration if
  2442.     // min=".." was set; we'll await being told of the
  2443.     // intrinsic duration of the media and THEN decide what
  2444.     // our duration should be:
  2445.     (0 == pElement->m_ulMinActiveDur  &&
  2446.     !pElement->m_bUseMediaDurForMinDur)  &&
  2447.     // /We also don't want to declare a dur yet if
  2448.     // max="media" in case the authored dur is greater than
  2449.     // the intrinsic duration:
  2450.     (!pElement->m_bUseMediaDurForMaxDur))
  2451.     {
  2452. if (WAY_IN_THE_FUTURE == pElement->m_ulDuration)
  2453. {
  2454.     HX_ASSERT(pElement->m_ulDuration > ulDelay);
  2455.     fDur = double(float(pElement->m_ulDuration - ulDelay));
  2456.     // /Don't multiply by partialPlayFactor if duration
  2457.     // is indefinite.
  2458. }
  2459. else
  2460. {
  2461.     HX_ASSERT(!pElement->m_bDurationIncludesDelayBeyondSyncbase);
  2462.     fDur = double(float(pElement->m_ulDuration));
  2463.     fDur *= pElement->m_pNode->m_fPartialPlayFactor;
  2464. }
  2465. pValues->SetPropertyULONG32("duration", ULONG32(float(fDur)) );
  2466. bDurationPropSet = TRUE;
  2467. ulDurationUsedInProperties = ULONG32(float(fDur));
  2468.     }
  2469.             // Save the value of pElement->m_ulDuration that
  2470.             // we set in the AddTrack IHXValues
  2471.             pElement->m_ulDurationInAddTrack = pElement->m_ulDuration;
  2472.     if(pElement->m_ulMaxDuration != (UINT32)-1)
  2473.     {
  2474. // /"Fixes" PR 47476 by not setting maxduration if duration
  2475. // prop is already set (to a same-or-lower value) for repeats.
  2476. // Otherwise, the core ignores the duration and uses the
  2477. // maxduration as the duration passed in through subsequent
  2478. // RepeatedTrackDurationSet() callback:
  2479. if (!bDurationPropSet  ||
  2480. pElement->m_pNode->m_repeatTag == RepeatUnknown  ||
  2481. ulDurationUsedInProperties > pElement->m_ulMaxDuration)
  2482. {
  2483.     ULONG32 ulMaxDuration = pElement->m_ulMaxDuration;
  2484.     if (ulDelay>0  &&  pElement->m_ulMaxDuration >= WAY_IN_THE_FUTURE)
  2485.     {
  2486. // /This fixes PR 81821: indef presentation duration was
  2487. // displaying as 22:22:22:27.2 instead of nothing shown.
  2488. // NOTE: we'll never get here if ulDelay >= WAY_IN...:
  2489. ulMaxDuration = WAY_IN_THE_FUTURE - ulDelay;
  2490.     }
  2491.     pValues->SetPropertyULONG32("maxduration", ulMaxDuration);
  2492. }
  2493.     }
  2494.     if(pElement->m_ulClipBegin != (UINT32)-1)
  2495.     {
  2496. pValues->SetPropertyULONG32("start", pElement->m_ulClipBegin);
  2497.     }
  2498.     if(pElement->m_ulClipEnd != (UINT32)-1)
  2499.     {
  2500. pValues->SetPropertyULONG32("end", pElement->m_ulClipEnd);
  2501.     }
  2502.     if (pElement->m_pNode->m_repeatTag != 
  2503.      RepeatUnknown)
  2504.     {
  2505. pValues->SetPropertyULONG32("repeatTag", pElement->m_pNode->m_repeatTag);
  2506.     }
  2507.             // Set the soundLevel property of the track.
  2508.             //
  2509.             // We need to check to see if this element is playing to a <region>.
  2510.             // If it is, then we will use the soundLevel attribute of that <region>.
  2511.             UINT32 ulSoundLevel = 100;
  2512.     BOOL bNeedToHandleSndLevelDueToLinkRgnTarget = FALSE;
  2513.             if (pElement->m_region.GetLength() > 0)
  2514.             {
  2515.                 CSmilBasicRegion* pRegion = getRegionByID(pElement->m_region);
  2516.                 if (pRegion)
  2517.                 {
  2518.     // /For PR 66650: if either source or destination level
  2519.     // of the link was not 100%, then we need to adjust one
  2520.     // up or down:
  2521.     if (100 != pElement->m_ulLinkTargetDestnLevel_pct  ||
  2522.     100 != pElement->m_ulLinkTargetSourceLevel_pct)
  2523.     {
  2524. bNeedToHandleSndLevelDueToLinkRgnTarget = TRUE;
  2525. ulSoundLevel = pElement->m_ulLinkTargetDestnLevel_pct;
  2526.     }
  2527.     else
  2528.     {
  2529. ulSoundLevel = UINT32(pRegion->m_dSoundLevel + 0.5);
  2530.     }
  2531.                 }
  2532.             }
  2533. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  2534.             // Also we need to check if an animation starts right at
  2535.             // the beginning of this track. If so, then we need to 
  2536.             // go ahead and set the soundLevel to be the first value
  2537.             // of the animation
  2538.             if (isAttributeAnimated(pElement->m_region, kAttrNameSoundLevel))
  2539.             {
  2540.                 // We ARE animating the soundLevel of this region, so loop
  2541.                 // through all the animation elements which are animating
  2542.                 // this region's soundLevel. If there are multiple animations
  2543.                 // going on at the same time, then we cannot attempt to
  2544.                 // try and calculate these - we have to just estimate. We 
  2545.                 // will take the min soundLevel.
  2546.                 BOOL   bFound     = FALSE;
  2547.                 UINT32 ulMinLevel = 0xFFFFFFFF;
  2548.                 CSmilAnimateElement* pAnim = getFirstAnimationElement(pElement->m_region,
  2549.                                                                       kAttrNameSoundLevel);
  2550.                 while (pAnim)
  2551.                 {
  2552.                     // Does this animation start at the same time this
  2553.                     // element starts?
  2554.                     if (pAnim->m_ulDelay == pElement->m_ulDelay)
  2555.                     {
  2556.                         // It DOES start at the same time, so get the first
  2557.                         // value of the animation
  2558.                         if (pAnim->m_ppValue &&
  2559.                             pAnim->m_ulNumValues >= 1 &&
  2560.                             pAnim->m_ppValue[0])
  2561.                         {
  2562.                             // We did find at least one matching
  2563.                             // animation, so set the flag
  2564.                             bFound = TRUE;
  2565.                             // Get the first value
  2566.                             UINT32 ulTmp = (UINT32) (pAnim->m_ppValue[0]->GetValueDouble() + 0.5);
  2567.                             // If it's less than the min, update the min
  2568.                             if (ulTmp < ulMinLevel)
  2569.                             {
  2570.                                 ulMinLevel = ulTmp;
  2571.                             }
  2572.                             
  2573.                         }
  2574.                     }
  2575.                     // Get the next animation
  2576.                     pAnim = getNextAnimationElement(pElement->m_region,
  2577.                                                     kAttrNameSoundLevel);
  2578.                 }
  2579.                 // If we found a matching animation, then set
  2580.                 // the soundLevel
  2581.                 if (bFound)
  2582.                 {
  2583.                     ulSoundLevel = ulMinLevel;
  2584.                 }
  2585.             }
  2586. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  2587.     // /For PR 66650: if this element was created for a link-targetted
  2588.     // region, then we may need to adjust soundLevel of currently-
  2589.     // playing audio tracks:
  2590.     if (bNeedToHandleSndLevelDueToLinkRgnTarget)
  2591.     {
  2592. // /Adjust all tracks' soundLevels (both source & dest)
  2593. // regardless of value, but skip setting dest's soundLevel if
  2594. // calculated level is 100:
  2595. if (100 != ulSoundLevel)
  2596.     pValues->SetPropertyULONG32("soundLevel", ulSoundLevel); 
  2597. // /then set all source tracks' soundLevels:
  2598. AdjustSoundLevelsOfAllCurrentTracks(
  2599. pElement->m_pNode->m_nGroup,
  2600. pElement->m_ulLinkTargetSourceLevel_pct,
  2601. pElement);
  2602.     }
  2603.     else
  2604.     {
  2605. pValues->SetPropertyULONG32("soundLevel", ulSoundLevel);
  2606.     }
  2607.     if (pElement->m_bIndefiniteDuration ||
  2608. pElement->m_bIndefiniteEnd)
  2609.     {
  2610. // /Adding this check fixes PR 73961:
  2611. if (WAY_IN_THE_FUTURE != pElement->m_ulDuration) 
  2612. {
  2613.     pValues->SetPropertyULONG32("indefiniteduration", TRUE);
  2614. }
  2615.     }
  2616.     if (bIsPrefetchElement)
  2617.     {
  2618. pValues->SetPropertyULONG32("PrefetchType",
  2619. pElement->m_typeOfPrefetchAmount);
  2620. pValues->SetPropertyULONG32("PrefetchValue",
  2621. pElement->m_ulPrefetchAmount);
  2622. HX_ASSERT(pElement->m_typeOfPrefetchAmount <
  2623. PrefetchMaxAllowedPlus1);
  2624.     }
  2625.     if (pElement->m_title.GetLength() > 0)
  2626.     {
  2627. setProperty(pValues, "title",
  2628. (const char*)pElement->m_title);
  2629.     }
  2630.     if (pElement->m_author.GetLength() > 0)
  2631.     {
  2632. setProperty(pValues, "author",
  2633. (const char*)pElement->m_author);
  2634.     }
  2635.     if (pElement->m_copyright.GetLength() > 0)
  2636.     {
  2637. setProperty(pValues, "copyright",
  2638. (const char*)pElement->m_copyright);
  2639.     }
  2640.     if (pElement->m_abstract.GetLength() > 0)
  2641.     {
  2642. setProperty(pValues, "abstract",
  2643. (const char*)pElement->m_abstract);
  2644.     }
  2645.     // add arbitrary name-value pairs to track
  2646.     if(pElement->m_pNode->m_pValues)
  2647.     {
  2648. IHXValues* pSrcValues = pElement->m_pNode->m_pValues;
  2649. const char* pName = 0;
  2650. IHXBuffer* pValue = 0;
  2651. HX_RESULT rCode = pSrcValues->GetFirstPropertyCString(
  2652.     pName, pValue);
  2653. while(HXR_OK == rCode)
  2654. {
  2655.     // skip the values we already have or have overridden...
  2656.     if((strcasecmp(pName, "url") != 0) &&
  2657.        (strcasecmp(pName, "id") != 0) &&
  2658.        (strcasecmp(pName, "playto") != 0) &&
  2659.        (strcasecmp(pName, "fill") != 0)  &&
  2660.        (strcasecmp(pName, "title") !=0)  &&
  2661.        (strcasecmp(pName, "author") !=0)  &&
  2662.        (strcasecmp(pName, "copyright") !=0)  &&
  2663.        (strcasecmp(pName, "abstract") !=0)  )
  2664.     {
  2665. setProperty(pValues, pName, 
  2666.     (const char*)pValue->GetBuffer());
  2667.     }
  2668.     HX_RELEASE(pValue);
  2669.     rCode = pSrcValues->GetNextPropertyCString(
  2670. pName, pValue);
  2671. }
  2672. HX_RELEASE(pValue);
  2673.     }
  2674.     {
  2675. // determine whether this source has been initialized yet...
  2676. BOOL     bHandled = FALSE;
  2677. SMILPlayToAssoc*    pPlayToAssoc = NULL;
  2678.   if(m_pPlayToAssocList  &&
  2679. // /Helps fix PR 50660 (par version) and PR 62408:
  2680. // don't repeat one that's merely restarting:
  2681. !pElement->IsRestartingAndNotRepeating())
  2682. {
  2683.     CHXSimpleList::Iterator i =m_pPlayToAssocList->Begin();
  2684.     for(;i!=m_pPlayToAssocList->End();++i)
  2685.     {
  2686. SMILPlayToAssoc* pThisAssoc = (SMILPlayToAssoc*)(*i);
  2687. if (pThisAssoc->m_repeatid == pElement->m_pNode->m_repeatid)
  2688. {
  2689.     IHXGroup2* pGroup2 = NULL;
  2690.     IHXTrack* pHXTrack = NULL;
  2691.     if (HXR_OK == pGroup->QueryInterface(IID_IHXGroup2, (void**)&pGroup2))
  2692.     {
  2693. if (HXR_OK == pGroup2->GetIHXTrack(pThisAssoc->m_uTrackIndex, pHXTrack) &&
  2694.     pHXTrack)
  2695. {
  2696.     if (!bDurationPropSet  &&
  2697.     pThisAssoc->m_ulDuration !=
  2698.     (UINT32)-1  &&
  2699.     1.0 != pElement->m_pNode->
  2700.     m_fPartialPlayFactor)
  2701.     {
  2702. double fDur = double(float(
  2703. pThisAssoc->m_ulDuration));
  2704. fDur *= pElement->m_pNode->
  2705. m_fPartialPlayFactor;
  2706. pElement->m_ulDuration =
  2707. ULONG32(float(fDur));
  2708. pValues->SetPropertyULONG32(
  2709. "duration",
  2710. pElement->m_ulDuration);
  2711.     }
  2712.     bHandled = TRUE;
  2713.     pHXTrack->AddRepeat(pValues);
  2714. }
  2715. HX_RELEASE(pHXTrack);
  2716.     }
  2717.     HX_RELEASE(pGroup2);
  2718.     if (bHandled)
  2719.     {
  2720. break;
  2721.     }
  2722. }
  2723.     }
  2724. }
  2725. if (!bHandled)
  2726. {
  2727.     SMILNode* pSyncNode = m_pSmilParser->getSyncAncestor(
  2728.     pElement->m_pNode);
  2729.     if (bIsPrefetchElement)
  2730.     {
  2731. IHXPrefetch* pPrefetch = NULL;
  2732. if (HXR_OK == pGroup->QueryInterface(IID_IHXPrefetch,
  2733. (void**)&pPrefetch))
  2734. {
  2735.                             // Add the rn:handledBy attribute to the 
  2736.                             // prefetch IHXValues
  2737.                             const char* pszHandledByStr =
  2738.                                 m_pSmilParser->getEnumAttrString(SMIL2AttrRNHandledBy,
  2739.                                                                  pElement->m_eHandledBy);
  2740.                             if (pszHandledByStr)
  2741.                             {
  2742.                                 addStringProperty(pValues,
  2743.                                                   m_pContext,
  2744.                                                   "handledBy",
  2745.                                                   pszHandledByStr);
  2746.                             }
  2747.     if (HXR_OK == pPrefetch->AddPrefetchTrack(pValues))
  2748.     {
  2749.                                 UINT32 ulTrackIndex = 0;
  2750.                                 // /Don't cast a UINT16& to a UINT32& here otherwise Big-endian
  2751.                                 // machines will not receive the right 2 bytes:
  2752.                                 rc = pValues->GetPropertyULONG32("TrackIndex", ulTrackIndex);
  2753.                                 pElement->m_pNode->m_nPrefetchTrackNum = (UINT16)ulTrackIndex;
  2754. HX_ASSERT(HXR_OK == rc);
  2755. if (!m_pPrefetchTrackElementMap)
  2756. {
  2757.     m_pPrefetchTrackElementMap = new CHXMapLongToObj;
  2758. }
  2759. CHXString* pId = new CHXString;
  2760. *pId = pElement->m_pNode->m_id;
  2761. (*m_pPrefetchTrackElementMap)[pElement->m_pNode->m_nPrefetchTrackNum] = pId;
  2762.     }
  2763. }
  2764. HX_RELEASE(pPrefetch);
  2765. // /Fixes PR 57135: prefetch element needs to be added
  2766. // to the timeline (i.e., to its parent) so its parent
  2767. // duration can resolve:
  2768. if ((UINT32)-1 != pElement->m_ulDuration)
  2769. {
  2770.     HX_ASSERT(pElement->m_ulDuration == pElement->getPureDuration());
  2771.          m_pSmilParser->durationResolved(
  2772.     (const char*)pElement->m_pNode->m_id,
  2773.     pElement->m_ulDuration);
  2774. }
  2775.     }
  2776.     else
  2777.     {
  2778.                         // Is the soundLevel animated?
  2779.                         if (isAttributeAnimated(pElement->m_region, kAttrNameSoundLevel)
  2780. // /This will be true if there exists an a or
  2781. // area element that messes with the audio
  2782. // level and has sourcePlaystate="play":
  2783. ||  m_pSmilParser->allTracksNeedReflushHint()
  2784. // /Or, is the flag set that tells us that
  2785. // this audio track might end on an event
  2786. // (including restarting on the fly):
  2787. ||  pElement->m_bAudioDeviceReflushHintNeeded)
  2788.                         {
  2789.     // /Track may be ended early (on-the-fly) OR
  2790.                             // The soundLevel on this track WILL be 
  2791.                             // animated - therefore, we need to add
  2792.                             // the following hint.
  2793. //                            // XXXMEH
  2794. //                            OutputDebugString("setting audioDeviceReflushHint track property to 1.n");
  2795.                             pValues->SetPropertyULONG32("audioDeviceReflushHint", 1);
  2796.                         }
  2797.                         // If mediaRepeat or any <param> elements
  2798.                         // are specified, then we need to add them to request parameters
  2799.                         IHXValues* pReqVal = NULL;
  2800.                         IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  2801.                         if (pFactory)
  2802.                         {
  2803.                             if (pElement->m_MediaRepeat.GetLength() > 0 ||
  2804.                                 hasParamChildren(pElement, TRUE))
  2805.                             {
  2806.                                 pFactory->CreateInstance(CLSID_IHXValues, (void**) &pReqVal);
  2807.                                 if (pReqVal)
  2808.                                 {
  2809.                                     if (pElement->m_MediaRepeat.GetLength() > 0)
  2810.                                     {
  2811.                                         addStringProperty(pReqVal, m_pContext,
  2812.                                                           "mediaRepeat",
  2813.                                                           pElement->m_MediaRepeat);
  2814.                                     }
  2815.                                     if (hasParamChildren(pElement, TRUE))
  2816.                                     {
  2817.                                         addParamProperties(pElement,
  2818.                                                            pReqVal,
  2819.                                                            m_pContext,
  2820.                                                            TRUE);
  2821.                                     }
  2822.                                 }
  2823.                             }
  2824.                         }
  2825. // /XXXEH- revisit this when we can handle groups of
  2826. // lock-sync'd-to-each-other tracks that are
  2827. // sync-independent of parallel tracks:
  2828. BOOL bSyncbaseIsSyncIndependent = FALSE;
  2829. if (pSyncNode  &&  pSyncNode->m_pElement  &&
  2830. SmilSyncBehaviorIndependent ==
  2831. pSyncNode->m_pElement->m_syncBehavior)
  2832. {
  2833.     bSyncbaseIsSyncIndependent = TRUE;
  2834. }
  2835. if (SmilSyncBehaviorIndependent !=
  2836. pElement->m_syncBehavior  &&
  2837. !bSyncbaseIsSyncIndependent)
  2838. {
  2839.     // Now add the track - if there are any request
  2840.     // parameters, then use AddTrack2
  2841.     if (pReqVal)
  2842.     {
  2843. // QI for IHXGroup2
  2844. IHXGroup2* pGroup2 = NULL;
  2845. pGroup->QueryInterface(IID_IHXGroup2,
  2846. (void**) &pGroup2);
  2847. if (pGroup2)
  2848. {
  2849.     rc = pGroup2->AddTrack2(pValues, pReqVal);
  2850. }
  2851. HX_RELEASE(pGroup2);
  2852.     }
  2853.     else
  2854.     {
  2855. rc = pGroup->AddTrack(pValues);
  2856.     }
  2857.     m_ulTrackIndex++;
  2858. }
  2859. // /track's syncBehavior="independent", so create a
  2860. // new child player for it:
  2861. else if (m_pParent)
  2862. {
  2863.     IHXClientEngine* pClientEngine =
  2864.     m_pParent->getClientEngine();
  2865.     if (pClientEngine)
  2866.     {
  2867. IHXPlayer* pTopLevelPlayer =
  2868. m_pParent->getPlayer();
  2869. IHXPlayer* pChildPlayer = NULL;
  2870. if (HXR_OK == pClientEngine->CreatePlayer(
  2871. pChildPlayer)  &&  pChildPlayer)
  2872. {
  2873.     IHXPlayerNavigator* pPlayerNavRoot=NULL;
  2874.     IHXPlayerNavigator* pPlayerNavKid=NULL;
  2875.     HX_RESULT pnrslt =
  2876.     pTopLevelPlayer->QueryInterface(
  2877.     IID_IHXPlayerNavigator,
  2878.     (void**)&pPlayerNavRoot);
  2879.     if (HXR_OK == pnrslt)
  2880.     {
  2881. HX_RESULT pnradd = pPlayerNavRoot->
  2882. AddChildPlayer(pChildPlayer);
  2883. UINT16 ulNumKids = pPlayerNavRoot->
  2884. GetNumChildPlayer();
  2885. pnrslt =
  2886. pChildPlayer->QueryInterface(
  2887. IID_IHXPlayerNavigator,
  2888. (void**)&pPlayerNavKid);
  2889. if (HXR_OK == pnrslt)
  2890. {
  2891.     HX_RESULT pnrspp =pPlayerNavKid->
  2892.     SetParentPlayer(
  2893.     pTopLevelPlayer);
  2894. }
  2895. #if defined(BE_SITE_SUPPLIER_20010205)
  2896. m_XXXEH_HACK_regionId =
  2897. pElement->m_region;
  2898. m_pIndependentPlayer = pChildPlayer;
  2899. const char* pPlayTo = (const char*)
  2900. pElement->m_region;
  2901. UINT32 ulLexicalNum = 0;
  2902. pValues->GetPropertyULONG32(
  2903. "lexicalNum", ulLexicalNum);
  2904. setPlayToAssoc(0, 9999+ulLexicalNum,
  2905. pElement->m_pNode->m_id,
  2906. pElement->m_pNode->m_repeatid,
  2907. (const char*)
  2908. pElement->m_region,
  2909. (const char*)
  2910. pElement->m_region, 
  2911. NULL /*pBeginTransition*/,
  2912. NULL /*pEndTransition*/,
  2913. ulLexicalNum);
  2914. // /We implement IHXSiteSupplier, so
  2915. // we'll say we're the context and
  2916. // then we'll get called with
  2917. // SitesNeeded by this player, and we
  2918. // can hook it up then:
  2919. pChildPlayer->SetClientContext(
  2920. (IHXSiteSupplier*)this);
  2921. #else
  2922. pChildPlayer->SetClientContext(
  2923. m_pContext);
  2924. #endif /* BE_SITE_SUPPLIER_20010205 */
  2925. HX_RESULT openrslt = HXR_FAIL;
  2926. // /Need IHXPlayer2 for OpenRequest():
  2927. IHXPlayer2* pPlayer2_Child = NULL;
  2928. // /XXXEH- hack for now; set begin,
  2929. // end, clip-begin, and clip-end as
  2930. // URL-encoded parameters:
  2931. char chDelimiter = '?';
  2932. CHXString extraURLparams = "";
  2933. if ((UINT32)-1 !=
  2934. pElement->m_ulDelay  &&
  2935. 0 != pElement->m_ulDelay)
  2936. {
  2937.     extraURLparams.Format(
  2938. "%cdelay=%.3f", chDelimiter,
  2939. (float)pElement->m_ulDelay /
  2940. 1000.0 );
  2941.     urlString += extraURLparams;
  2942.     extraURLparams = "";
  2943.     chDelimiter = '&';
  2944. }
  2945. if (-1 != fDur)
  2946. {
  2947.     extraURLparams.Format(
  2948. "%cduration=%.3f", 
  2949. chDelimiter,