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

Symbian

开发平台:

Visual C++

  1.                 pPort->m_pSiteUser == pSiteUser)
  2.             {
  3.                 pRet = pPort;
  4.                 break;
  5.             }
  6.         }
  7.     }
  8.     return pRet;
  9. }
  10. CSmilBasicViewport* CSmilDocumentRenderer::getViewportBySite(IHXSite* pSite)
  11. {
  12.     CSmilBasicViewport* pRet = NULL;
  13.     if(m_pViewportList)
  14.     {
  15.         LISTPOSITION pos = m_pViewportList->GetHeadPosition();
  16.         while (pos)
  17.         {
  18.             CSmilBasicViewport* pPort =
  19.                 (CSmilBasicViewport*) m_pViewportList->GetNext(pos);
  20.             if (pPort &&
  21.                 pPort->m_pSite == pSite)
  22.             {
  23.                 pRet = pPort;
  24.                 break;
  25.             }
  26.         }
  27.     }
  28.     return pRet;
  29. }
  30. CSmilBasicViewport* CSmilDocumentRenderer::getViewportByDescendant(CSmilBasicRegion* pRegion)
  31. {
  32.     CSmilBasicViewport* pRet = NULL;
  33.     if (pRegion && !pRegion->m_bUnderRootLayout)
  34.     {
  35.         CSmilBasicBox* pTop = getTopLevelBox(pRegion);
  36.         if (pTop)
  37.         {
  38.             pRet = (CSmilBasicViewport*) pTop;
  39.         }
  40.     }
  41.     return pRet;
  42. }
  43. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  44. CSmilBasicBox* CSmilDocumentRenderer::getTopLevelBox(CSmilBasicRegion* pRegion)
  45. {
  46.     CSmilBasicBox* pRet = NULL;
  47.     if (pRegion && pRegion->m_pParent)
  48.     {
  49.         pRet = pRegion->m_pParent;
  50.         while (pRet->m_pParent)
  51.         {
  52.             pRet = pRet->m_pParent;
  53.         }
  54.     }
  55.     return pRet;
  56. }
  57. CSmilRegPoint* CSmilDocumentRenderer::getRegPoint(const char* pszID)
  58. {
  59.     CSmilRegPoint* pRet = NULL;
  60.     if(m_pRegPointMap)
  61.     {
  62.         void* pVoid = NULL;
  63.         if (m_pRegPointMap->Lookup(pszID, pVoid))
  64.         {
  65.             pRet = (CSmilRegPoint*) pVoid;
  66.         }
  67.     }
  68.     return pRet;
  69. }
  70. CSmilSource* CSmilDocumentRenderer::getSource(const char* pszID)
  71. {
  72.     CSmilSource* pRet = NULL;
  73.     if (m_pSmilParser)
  74.     {
  75.         CSmilElement* pElement = m_pSmilParser->findElement(pszID);
  76.         if (pElement && pElement->m_pNode &&
  77.             (pElement->m_pNode->m_tag == SMILRef        ||
  78.              pElement->m_pNode->m_tag == SMILText       ||
  79.              pElement->m_pNode->m_tag == SMILImg        ||
  80.              pElement->m_pNode->m_tag == SMILAudio      ||
  81.              pElement->m_pNode->m_tag == SMILVideo      ||
  82.              pElement->m_pNode->m_tag == SMILAnimation  ||
  83.              pElement->m_pNode->m_tag == SMILTextstream ||
  84.              pElement->m_pNode->m_tag == SMILBrush      ||
  85.              pElement->m_pNode->m_tag == SMILPrefetch))
  86.         {
  87.             pRet = (CSmilSource*) pElement;
  88.         }
  89.     }
  90.     return pRet;
  91. }
  92. void CSmilDocumentRenderer::setTopLevelSiteSize()
  93. {
  94.     if (m_pRootLayout->IsWidthSet() &&
  95. m_pRootLayout->IsHeightSet())
  96.     {
  97.         // Set the members
  98.         m_topSiteSize.cx         = (INT32) m_pRootLayout->GetWidth();
  99.         m_topSiteSize.cy         = (INT32) m_pRootLayout->GetHeight();
  100.         m_topSiteOriginalSize.cx = m_topSiteSize.cx;
  101.         m_topSiteOriginalSize.cy = m_topSiteSize.cy;
  102.         // Set the site's size
  103.         if(m_topSiteSize.cx > 0 && m_topSiteSize.cy > 0 &&
  104.            m_pRootLayout && m_pRootLayout->m_pSite)
  105.         {
  106.             // Get the site's current size
  107.             HXxSize cSize = {0, 0};
  108.             m_pRootLayout->m_pSite->GetSize(cSize);
  109.             // If the size we want to set and the current
  110.             // size are different, then call SetSize()
  111.             if (cSize.cx != m_topSiteSize.cx ||
  112.                 cSize.cy != m_topSiteSize.cy)
  113.             {
  114.                 m_pRootLayout->m_pSite->SetSize(m_topSiteSize);
  115.             }
  116.         }
  117.     }
  118. }
  119. HX_RESULT CSmilDocumentRenderer::setRegionParentChild(CSmilBasicRegion* pRegion)
  120. {
  121.     HX_RESULT retVal = HXR_OK;
  122.     if (pRegion &&
  123.         pRegion->m_pSmilRegion &&
  124.         pRegion->m_pSmilRegion->m_pNode &&
  125.         pRegion->m_pSmilRegion->m_pNode->m_pParent)
  126.     {
  127.         SMILNodeTag eParentTag = pRegion->m_pSmilRegion->m_pNode->m_pParent->m_tag;
  128.         CHXString   cParentID  = pRegion->m_pSmilRegion->m_pNode->m_pParent->m_id;
  129.         if (eParentTag == SMILBasicLayout)
  130.         {
  131.             // Does the root layout exist?
  132.             if (!m_pRootLayout)
  133.             {
  134.                 // Create a root layout
  135.                 m_pRootLayout = new CSmilBasicRootLayout();
  136.             }
  137.             if (m_pRootLayout)
  138.             {
  139.                 // Set our own parent member
  140.                 pRegion->m_pParent = m_pRootLayout;
  141.                 // Add a child to the root-layout
  142.                 retVal = m_pRootLayout->addChild(pRegion);
  143.             }
  144.             else
  145.             {
  146.                 retVal = HXR_OUTOFMEMORY;
  147.             }
  148.         }
  149.         else if (eParentTag == SMILRegion)
  150.         {
  151.             CSmilBasicRegion* pParent = getRegionByID(cParentID);
  152.             if (pParent)
  153.             {
  154.                 // Set our own parent member
  155.                 pRegion->m_pParent = pParent;
  156.                 // Add ourselves as a child of our parent
  157.                 retVal = pParent->addChild(pRegion);
  158.                 if (SUCCEEDED(retVal))
  159.                 {
  160.                     // Copy our parent's flag which says
  161.                     // whether or not we are descended from
  162.                     // the root-layout
  163.                     pRegion->m_bUnderRootLayout = pParent->m_bUnderRootLayout;
  164.                 }
  165.             }
  166.             else
  167.             {
  168.                 retVal = HXR_FAIL;
  169.             }
  170.         }
  171. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  172.         else if (eParentTag == SMILViewport)
  173.         {
  174.             CSmilBasicViewport* pPort = getViewport(cParentID);
  175.             if (pPort)
  176.             {
  177.                 // Set our own parent member
  178.                 pRegion->m_pParent = pPort;
  179.                 // Add ourselves as a child of our parent
  180.                 pPort->addChild(pRegion);
  181.                 // Clear the flag that says we are a descendant
  182.                 // of the root layout
  183.                 pRegion->m_bUnderRootLayout = FALSE;
  184.             }
  185.             else
  186.             {
  187.                 retVal = HXR_FAIL;
  188.             }
  189.         }
  190. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  191.     }
  192.     return retVal;
  193. }
  194. HX_RESULT CSmilDocumentRenderer::createRegionSites(CHXSimpleList* pChildList)
  195. {
  196.     HX_RESULT retVal = HXR_OK;
  197.     // Don't do anything if we don't have any children
  198.     if (pChildList)
  199.     {
  200.         // Loop through the children
  201.         LISTPOSITION pos = pChildList->GetHeadPosition();
  202.         while (pos && SUCCEEDED(retVal))
  203.         {
  204.             // Get the child region
  205.             CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pChildList->GetNext(pos);
  206.             if (pRegion)
  207.             {
  208.                 // Setup the site for this region
  209.                 retVal = createRegionSite(pRegion);
  210.                 if (SUCCEEDED(retVal))
  211.                 {
  212.                     // We have successfully processed this region,
  213.                     // so now process its children
  214.                     retVal = createRegionSites(pRegion->m_pChildList);
  215.                 }
  216.             }
  217.         }
  218.     }
  219.     return retVal;
  220. }
  221. HX_RESULT CSmilDocumentRenderer::createRegionSite(CSmilBasicRegion* pRegion)
  222. {
  223.     HX_RESULT retVal = HXR_OK;
  224.     if (pRegion &&
  225.         pRegion->m_pParent &&
  226.         pRegion->m_pParent->m_pSite)
  227.     {
  228.         // Make sure we don't already have a site
  229.         HX_RELEASE(pRegion->m_pSite);
  230.         // Create the site from its parent site - this
  231.         // could either be a top-level site (root-layout
  232.         // or viewport) or another region's site
  233.         retVal = pRegion->m_pParent->m_pSite->CreateChild(pRegion->m_pSite);
  234.         if (SUCCEEDED(retVal))
  235.         {
  236.             // Set the position of the site
  237.             HXxPoint cPos = {pRegion->m_Rect.left, pRegion->m_Rect.top};
  238. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  239. #if defined(XXXMEH_DO_VIEWPORT_TLC) && defined(_WINDOWS)
  240.             if (pRegion->m_pParent &&
  241.                 !pRegion->m_pParent->m_pParent &&
  242.                 !pRegion->m_bUnderRootLayout)
  243.             {
  244.                 cPos.x += GetSystemMetrics(SM_CXFIXEDFRAME);
  245.                 cPos.y += GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
  246.             }
  247. #endif
  248. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  249.             MLOG_LAYOUT(m_pErrorMessages,
  250.                         "createRegionSite() region=%s SetSize(%ld,%ld)n",
  251.                         (const char*) pRegion->m_region, cPos.x, cPos.y);
  252.             retVal = pRegion->m_pSite->SetPosition(cPos);
  253.             if (SUCCEEDED(retVal))
  254.             {
  255.                 // Set the size of the site
  256.                 HXxSize cSize = {HXxRECT_WIDTH(pRegion->m_Rect),
  257.                                  HXxRECT_HEIGHT(pRegion->m_Rect)};
  258.                 MLOG_LAYOUT(m_pErrorMessages,
  259.                             "createRegionSite() region=%s SetSize(%ld,%ld)n",
  260.                             (const char*) pRegion->m_region, cSize.cx, cSize.cy);
  261.                 retVal = pRegion->m_pSite->SetSize(cSize);
  262.                 if (SUCCEEDED(retVal))
  263.                 {
  264.                     // Since region's have a backgroundColor, then
  265.                     // we have to create a site user which will 
  266.                     // draw this background color.
  267.                     HX_RELEASE(pRegion->m_pSiteUser);
  268.                     pRegion->m_pSiteUser = new CSmilSiteUser((CSmilSiteUserResponse*) this,
  269.                                                              pRegion->m_ulBackgroundColor,
  270.                                                              m_pContext, FALSE, pRegion->m_region);
  271.                     if (pRegion->m_pSiteUser)
  272.                     {
  273.                         // AddRef the site user
  274.                         pRegion->m_pSiteUser->AddRef();
  275.                         // Attach this site user to the site
  276.                         retVal = pRegion->m_pSite->AttachUser(pRegion->m_pSiteUser);
  277.                         if (SUCCEEDED(retVal))
  278.                         {
  279.                             // If this region has a showBackground="always", then
  280.                             // make it visible. Otherwise, hide it - the show event
  281.                             // for the media playing in the region will make it
  282.                             // visible later
  283.                             if (pRegion->m_eShowBackground == ShowBackgroundAlways)
  284.                             {
  285.                                 showSite(pRegion->m_pSite, TRUE);
  286.                             }
  287.                             else if (pRegion->m_eShowBackground == ShowBackgroundWhenActive)
  288.                             {
  289.                                 showSite(pRegion->m_pSite, FALSE);
  290.                             }
  291.                         }
  292.                     }
  293.                     else
  294.                     {
  295.                         retVal = HXR_OUTOFMEMORY;
  296.                     }
  297.                 }
  298.             }
  299.         }
  300.     }
  301.     else
  302.     {
  303.         retVal = HXR_FAIL;
  304.     }
  305.     return retVal;
  306. }
  307. void CSmilDocumentRenderer::destroyRegionSites(CHXSimpleList* pChildList)
  308. {
  309.     // Do we have any children?
  310.     if (pChildList)
  311.     {
  312.         // Loop through the children
  313.         LISTPOSITION pos = pChildList->GetHeadPosition();
  314.         while (pos)
  315.         {
  316.             // Get the region
  317.             CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pChildList->GetNext(pos);
  318.             if (pRegion)
  319.             {
  320.                 // We have to process our children first
  321.                 destroyRegionSites(pRegion->m_pChildList);
  322.                 // Do we have a site to destroy?
  323.                 if (pRegion->m_pParent &&
  324.                     pRegion->m_pParent->m_pSite &&
  325.                     pRegion->m_pSite)
  326.                 {
  327.                     // Detach the site user - our ref on it will
  328.                     // get released when the CSmilBasicRegion is
  329.                     // destructed
  330.                     pRegion->m_pSite->DetachUser();
  331.                     // Destroy the parent-child relationship
  332.                     pRegion->m_pParent->m_pSite->DestroyChild(pRegion->m_pSite);
  333.                 }
  334.             }
  335.         }
  336.     }
  337. }
  338. CSmilBasicRegion* CSmilDocumentRenderer::getRegionByName(const char* pszName)
  339. {
  340.     CSmilBasicRegion* pRet = NULL;
  341.     if (pszName && m_pRegionMap)
  342.     {
  343.         while (m_pRegionMapIterator)
  344.         {
  345.             const char* pszKey = NULL;
  346.             void*       pVoid  = NULL;
  347.             m_pRegionMap->GetNextAssoc(m_pRegionMapIterator, pszKey, pVoid);
  348.             if (pVoid)
  349.             {
  350.                 CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pVoid;
  351.                 if (pRegion->m_pSmilRegion &&
  352.                     pRegion->m_pSmilRegion->m_RegionName.GetLength() > 0 &&
  353.                     strlen(pszName)                                  > 0 &&
  354.                     pRegion->m_pSmilRegion->m_RegionName == pszName)
  355.                 {
  356.                     pRet = pRegion;
  357.                     break;
  358.                 }
  359.             }
  360.         }
  361.     }
  362.     return pRet;
  363. }
  364. STDMETHODIMP CSmilDocumentRenderer::SitePositionChanged(IHXSite* pSite, HXxPoint* pPoint)
  365. {
  366.     HX_RESULT retVal = HXR_OK;
  367.     return retVal;
  368. }
  369. STDMETHODIMP CSmilDocumentRenderer::SiteSizeChanged(IHXSite* pSite, HXxSize* pSize)
  370. {
  371.     HX_RESULT retVal = HXR_OK;
  372.     if (pSite && pSize)
  373.     {
  374.         if (m_pRootLayout &&
  375.             m_pRootLayout->m_pSite &&
  376.             pSite == m_pRootLayout->m_pSite)
  377.         {
  378.             // check for resize of top level site, we must have
  379.             // a "site" and not already be resizing!
  380.             if (!m_pRootLayout->m_bSiteChangingSize)
  381.             {
  382.                 if (pSize->cx != HXxRECT_WIDTH(m_pRootLayout->m_Rect) ||
  383.                     pSize->cy != HXxRECT_HEIGHT(m_pRootLayout->m_Rect))
  384.                 {
  385.                     MLOG_LAYOUT(m_pErrorMessages,
  386.                                 "SiteSizeChanged(%ld,%ld) root-layout m_ulCurrentTime=%lu t=%lun",
  387.                                 pSize->cx, pSize->cy, m_ulCurrentTime, HX_GET_BETTERTICKCOUNT());
  388.                     m_pRootLayout->m_bSiteChangingSize = TRUE;
  389.                     resizeTopLevelBox(m_pRootLayout, m_pRootLayout->m_OriginalSize, *pSize);
  390.                     forceFullRedraw(m_pRootLayout->m_pSite);
  391.                     m_pRootLayout->m_bSiteChangingSize = FALSE;
  392.                 }
  393.             }
  394.         }
  395. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  396.         else
  397.         {
  398.             CSmilBasicViewport* pPort = getViewportBySite(pSite);
  399.             if (pPort)
  400.             {
  401.                 // check for resize of top level site, we must have
  402.                 // a "site" and not already be resizing!
  403.                 if (!pPort->m_bSiteChangingSize)
  404.                 {
  405.                     if (pSize->cx != HXxRECT_WIDTH(pPort->m_Rect) ||
  406.                         pSize->cy != HXxRECT_HEIGHT(pPort->m_Rect))
  407.                     {
  408.                         pPort->m_bSiteChangingSize = TRUE;
  409.                         resizeTopLevelBox(pPort, pPort->m_OriginalSize, *pSize);
  410.                         forceFullRedraw(pPort->m_pSite);
  411.                         pPort->m_bSiteChangingSize = FALSE;
  412.                     }
  413.                 }
  414.             }
  415.         }
  416. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  417.     }
  418.     else
  419.     {
  420.         retVal = HXR_FAIL;
  421.     }
  422.     return retVal;
  423. }
  424. STDMETHODIMP CSmilDocumentRenderer::BeginDone(UINT16 uGroupIndex, UINT16 uTrackIndex)
  425. {
  426.     HX_RESULT retVal = HXR_OK;
  427.     return retVal;
  428. }
  429. STDMETHODIMP CSmilDocumentRenderer::SeekDone(UINT16 uGroupIndex, UINT16 uTrackIndex,
  430.                                              UINT32 ulSeekTime)
  431. {
  432.     HX_RESULT retVal = HXR_OK;
  433.     return retVal;
  434. }
  435. STDMETHODIMP CSmilDocumentRenderer::PauseDone(UINT16 uGroupIndex, UINT16 uTrackIndex)
  436. {
  437.     HX_RESULT retVal = HXR_OK;
  438.     return retVal;
  439. }
  440. STDMETHODIMP CSmilDocumentRenderer::StopDone(UINT16 uGroupIndex, UINT16 uTrackIndex)
  441. {
  442.     HX_RESULT retVal = HXR_OK;
  443.     return retVal;
  444. }
  445. STDMETHODIMP CSmilDocumentRenderer::OnSoundLevelAnimation(UINT16 uGroupIndex,
  446.                                                           UINT16 uTrackIndex,
  447.                                                           UINT32 ulSoundLevelAnimationTime)
  448. {
  449.     // XXXMEH
  450. //    char szDbgStr[256];
  451. //    sprintf(szDbgStr, "enter OnSoundLevelAnimation(%u,%u,%lu) m_ulCurrentTime=%lu tick=%lu threadID=%lun",
  452. //            uGroupIndex, uTrackIndex, ulSoundLevelAnimationTime,
  453. //            m_ulCurrentTime, HX_GET_BETTERTICKCOUNT(), GetCurrentThreadId());
  454. //    OutputDebugString(szDbgStr);
  455.     HX_RESULT retVal = HXR_OK;
  456. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  457.     // Get the playto assocation
  458.     SMILPlayToAssoc* pPlayTo = getPlayToAssoc(uGroupIndex, uTrackIndex);
  459.     if (pPlayTo)
  460.     {
  461.         // If there is another animation getting added right
  462.         // now, then we need to hold up until it is added
  463.         if (m_pSoundLevelMutex) m_pSoundLevelMutex->Lock();
  464.         // Find the animation element which is animating
  465.         // the soundLevel of this region
  466.         // XXXMEH - TODO - replace this with a more efficient method
  467.         // of finding the correct animation sandwich
  468.         CSmilAnimateInfo* pInfo = NULL;
  469.         if (m_pActiveAnimations)
  470.         {
  471.             LISTPOSITION pos = m_pActiveAnimations->GetHeadPosition();
  472.             while (pos)
  473.             {
  474.                 CSmilAnimateInfo* pListInfo =
  475.                     (CSmilAnimateInfo*) m_pActiveAnimations->GetNext(pos);
  476.                 if (pListInfo &&
  477.                     pListInfo->m_pSandwich)
  478.                 {
  479.                     CHXString cRegionID(pListInfo->m_pSandwich->GetTargetElementID());
  480.                     if (cRegionID == pPlayTo->m_playTo &&
  481.                         pListInfo->m_pSandwich->GetAttributeName() == kAttrNameSoundLevel)
  482.                     {
  483.                         pInfo = pListInfo;
  484.                         break;
  485.                     }
  486.                 }
  487.             }
  488.         }
  489.         // Now compute the value of the animation at
  490.         // the time we were given
  491.         if (pInfo && pInfo->m_pSandwich && pInfo->m_pUnder)
  492.         {
  493.             // We want to cap the time at the duration of
  494.             // the current group - we don't want to send
  495.             // a timesync that is greater than the duration.
  496.             UINT32 ulAnimTime = ulSoundLevelAnimationTime;
  497.             if (ulAnimTime > m_ulCurGroupDuration &&
  498.                 m_ulCurGroupDuration > 0)
  499.             {
  500.                 ulAnimTime = m_ulCurGroupDuration;
  501.             }
  502.             // Compute the value of the animation at the time
  503.             CAttr cRet = pInfo->m_pSandwich->GetValue(ulAnimTime,
  504.                                                       pInfo->m_pUnder,
  505.                                                       pInfo->m_pDepend);
  506.             // Get the sound level and clamp it at 0 on the bottom end.
  507.             double dVal = cRet.GetValueDouble();
  508.             if (dVal < 0.0) dVal = 0.0;
  509.             // XXXMEH - what should we clamp it to at the top end?
  510.             // I'll choose 10x as the limit for now, which would be 1000%.
  511.             if (dVal > MAX_ALLOWED_SOUNDLEVEL) dVal = MAX_ALLOWED_SOUNDLEVEL;
  512.             // Get this value as a UINT16
  513.             UINT16 usLevel = (UINT16) (dVal + 0.5);
  514.             // Set the soundLevel for the track
  515.             IHXTrack* pTrack = NULL;
  516.             HX_RESULT  rv     = getTrack(uGroupIndex, uTrackIndex, pTrack);
  517.             if (SUCCEEDED(rv))
  518.             {
  519.                 MLOG_ANIM(m_pErrorMessages,"OnSoundLevelAnimation(%u,%u,%lu) m_ulCurrentTime=%lu "
  520.                           "tick=%lu I call SetSoundLevel(%u)n",
  521.                           uGroupIndex, uTrackIndex, ulSoundLevelAnimationTime,
  522.                           m_ulCurrentTime, HX_GET_BETTERTICKCOUNT(), usLevel);
  523.                 pTrack->SetSoundLevel(usLevel);
  524.             }
  525.             HX_RELEASE(pTrack);
  526.             // Adjust the sandwich
  527.             pInfo->m_pSandwich->AdjustLayers(ulAnimTime);
  528.             // Are there no more layers left in this animation?
  529.             if (pInfo->m_pSandwich->GetNumLayers() == 0)
  530.             {
  531.                 // This animation is done, so finish call
  532.                 // IHXTrack::EndSoundLevelAnimation
  533.                 finishSoundLevelAnimation(pInfo);
  534.                 // Remove the animation from the active 
  535.                 // animation list
  536.                 removeAnimation(pInfo);
  537.                 // Now we can delete the info object
  538.                 HX_DELETE(pInfo);
  539.             }
  540.         }
  541.         // Now we can release the mutex, since we
  542.         // are done messing with the animations.
  543.         if (m_pSoundLevelMutex) m_pSoundLevelMutex->Unlock();
  544.     }
  545.     else
  546.     {
  547.         retVal = HXR_FAIL;
  548.     }
  549. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  550.     // XXXMEH
  551. //    sprintf(szDbgStr, "exit  OnSoundLevelAnimation(%u,%u,%lu) m_ulCurrentTime=%lu tick=%lu threadID=%lun",
  552. //            uGroupIndex, uTrackIndex, ulSoundLevelAnimationTime,
  553. //            m_ulCurrentTime, HX_GET_BETTERTICKCOUNT(), GetCurrentThreadId());
  554. //    OutputDebugString(szDbgStr);
  555.     return retVal;
  556. }
  557. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  558. STDMETHODIMP CSmilDocumentRenderer::ViewPortOpened(const char* pszViewPort)
  559. {
  560.     HX_RESULT retVal = HXR_FAIL;
  561.     if (pszViewPort)
  562.     {
  563.         CSmilBasicViewport* pPort = getViewport(pszViewPort);
  564.         if (pPort)
  565.         {
  566.             // Set the open flag
  567.             pPort->m_bOpen = TRUE;
  568.             // Clear the return value
  569.             retVal = HXR_OK;
  570.     // /Raise the "open" event:
  571.     HX_RESULT rc = m_pSmilParser->tryToResolveBeginEndEvents(
  572.     "topLayoutOpenEvent", pszViewPort, m_ulCurrentTime);
  573.     if SUCCEEDED(rc)
  574.     {
  575. handleElements();
  576.     }
  577.         }
  578.     }
  579.     return retVal;
  580. }
  581. STDMETHODIMP CSmilDocumentRenderer::ViewPortClosed(const char* pszViewPort)
  582. {
  583.     HX_RESULT retVal = HXR_FAIL;
  584.     if (pszViewPort)
  585.     {
  586.         CSmilBasicViewport* pPort = getViewport(pszViewPort);
  587.         if (pPort)
  588.         {
  589.             // Clear the open flag
  590.             pPort->m_bOpen = FALSE;
  591.             // Clear the return value
  592.             retVal = HXR_OK;
  593.     // /Raise the "close" event:
  594.     HX_RESULT rc = m_pSmilParser->tryToResolveBeginEndEvents(
  595.     "topLayoutCloseEvent", pszViewPort, m_ulCurrentTime);
  596.     if SUCCEEDED(rc)
  597.     {
  598. handleElements();
  599.     }
  600.         }
  601.     }
  602.     return retVal;
  603. }
  604. STDMETHODIMP CSmilDocumentRenderer::ViewPortShown(const char* pszViewPort)
  605. {
  606.     HX_RESULT retVal = HXR_OK;
  607.     return retVal;
  608. }
  609. STDMETHODIMP CSmilDocumentRenderer::ViewPortHidden(const char* pszViewPort)
  610. {
  611.     HX_RESULT retVal = HXR_OK;
  612.     return retVal;
  613. }
  614. STDMETHODIMP CSmilDocumentRenderer::ViewPortFocusSet(const char* pszViewPort)
  615. {
  616.     HX_RESULT retVal = HXR_OK;
  617.     return retVal;
  618. }
  619. STDMETHODIMP CSmilDocumentRenderer::ViewPortZOrderSet(const char* pszViewPort, UINT32 ulZOrder)
  620. {
  621.     HX_RESULT retVal = HXR_OK;
  622.     return retVal;
  623. }
  624. #ifdef XXXMEH_DO_VIEWPORT_TLC
  625. STDMETHODIMP CSmilDocumentRenderer::OnViewPortOpen(IHXValues* pValues, IHXSiteUser* pSiteUser)
  626. {
  627.     HX_RESULT retVal = HXR_OK;
  628.     if (pValues && m_pContext)
  629.     {
  630.         // Get the common class factory interface
  631.         IHXCommonClassFactory* pFactory = NULL;
  632.         retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  633.                                             (void**) &pFactory);
  634.         if (SUCCEEDED(retVal))
  635.         {
  636.             // Create an IHXSiteWindowed
  637.             IHXSiteWindowed* pSiteWindowed = NULL;
  638.             retVal = pFactory->CreateInstance(CLSID_IHXSiteWindowed,
  639.                                               (void**) &pSiteWindowed);
  640.             if (SUCCEEDED(retVal))
  641.             {
  642.                 // Call Create() on the site
  643.                 UINT32 ulStyle = 0;
  644. #if defined(_WINDOWS)
  645.                 ulStyle = WS_CAPTION | WS_SIZEBOX | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
  646. #endif
  647.                 retVal = pSiteWindowed->Create(NULL, ulStyle);
  648.                 if (SUCCEEDED(retVal))
  649.                 {
  650.                     // Get the IHXSite interface
  651.                     IHXSite* pSite = NULL;
  652.                     retVal = pSiteWindowed->QueryInterface(IID_IHXSite,
  653.                                                            (void**) &pSite);
  654.                     if (SUCCEEDED(retVal))
  655.                     {
  656.                         // Get the "playto" property
  657.                         IHXBuffer* pPlayToStr = NULL;
  658.                         retVal = pValues->GetPropertyCString("playto", pPlayToStr);
  659.                         if (SUCCEEDED(retVal))
  660.                         {
  661.                             // Get the string
  662.                             const char* pszPlayTo = (const char*) pPlayToStr->GetBuffer();
  663.                             // Get the IHXValues interface from the site
  664.                             IHXValues* pSiteValues = NULL;
  665.                             pSite->QueryInterface(IID_IHXValues, (void**) &pSiteValues);
  666.                             if (pSiteValues)
  667.                             {
  668.                                 // Set the "name" property in the site properties
  669.                                 pSiteValues->SetPropertyCString("name", pPlayToStr);
  670.                                 // Get the viewport
  671.                                 CSmilBasicViewport* pPort = getViewport(pszPlayTo);
  672.                                 if (pPort && pPort->m_pSiteUser)
  673.                                 {
  674.                                     // QI for IHXSiteUser
  675.                                     IHXSiteUser* pSiteUser = NULL;
  676.                                     retVal = pPort->m_pSiteUser->QueryInterface(IID_IHXSiteUser,
  677.                                                                                 (void**) &pSiteUser);
  678.                                     if (SUCCEEDED(retVal))
  679.                                     {
  680.                                         // Add the viewport site to the map
  681.                                         if (!m_pViewPortSiteMap)
  682.                                         {
  683.                                             m_pViewPortSiteMap = new CHXMapStringToOb();
  684.                                         }
  685.                                         if (m_pViewPortSiteMap)
  686.                                         {
  687.                                             // AddRef the site before going in the map
  688.                                             pSite->AddRef();
  689.                                             // Put it into the map
  690.                                             m_pViewPortSiteMap->SetAt(pszPlayTo, pSite);
  691.                                         }
  692.                                         // Attach the viewport's site user to the site
  693.                                         retVal = pSite->AttachUser(pSiteUser);
  694.                                     }
  695.                                     HX_RELEASE(pSiteUser);
  696.                                 }
  697.                                 else
  698.                                 {
  699.                                     retVal = HXR_FAIL;
  700.                                 }
  701.                             }
  702.                             HX_RELEASE(pSiteValues);
  703.                         }
  704.                         HX_RELEASE(pPlayToStr);
  705.                     }
  706.                     HX_RELEASE(pSite);
  707.                 }
  708.             }
  709.             HX_RELEASE(pSiteWindowed);
  710.         }
  711.         HX_RELEASE(pFactory);
  712.     }
  713.     else
  714.     {
  715.         retVal = HXR_FAIL;
  716.     }
  717.     return retVal;
  718. }
  719. STDMETHODIMP CSmilDocumentRenderer::OnViewPortClose(const char* pszViewPort)
  720. {
  721.     HX_RESULT retVal = HXR_FAIL;
  722.     if (pszViewPort && m_pViewPortSiteMap)
  723.     {
  724.         void* pObj = NULL;
  725.         if (m_pViewPortSiteMap->Lookup(pszViewPort, pObj))
  726.         {
  727.             // Get the site
  728.             IHXSite* pSite = (IHXSite*) pObj;
  729.             // Remove it from the map
  730.             m_pViewPortSiteMap->RemoveKey(pszViewPort);
  731.             // Detach the user
  732.             pSite->DetachUser();
  733.             // Since we called IHXSiteWindowed::Create(), then
  734.             // we need to call IHXSiteWindowed::Destroy() as well.
  735.             IHXSiteWindowed* pSiteWindowed = NULL;
  736.             pSite->QueryInterface(IID_IHXSiteWindowed, (void**) &pSiteWindowed);
  737.             if (pSiteWindowed)
  738.             {
  739.                 pSiteWindowed->Destroy();
  740.             }
  741.             HX_RELEASE(pSiteWindowed);
  742.             // Release the map's ref on the site
  743.             HX_RELEASE(pSite);
  744.             // Clear the return value
  745.             retVal = HXR_OK;
  746.         }
  747.     }
  748.     return retVal;
  749. }
  750. STDMETHODIMP CSmilDocumentRenderer::OnViewPortShow(const char* pszViewPort)
  751. {
  752.     HX_RESULT retVal = HXR_FAIL;
  753.     if (pszViewPort && m_pViewPortSiteMap)
  754.     {
  755.         void* pObj = NULL;
  756.         if (m_pViewPortSiteMap->Lookup(pszViewPort, pObj) && pObj)
  757.         {
  758.             // Get the site
  759.             IHXSite* pSite = (IHXSite*) pObj;
  760.             // Do a show on the site
  761.             showSite(pSite, TRUE);
  762.             // Clear the return value
  763.             retVal = HXR_OK;
  764.         }
  765.     }
  766.     return retVal;
  767. }
  768. STDMETHODIMP CSmilDocumentRenderer::OnViewPortHide(const char* pszViewPort)
  769. {
  770.     HX_RESULT retVal = HXR_FAIL;
  771.     if (pszViewPort && m_pViewPortSiteMap)
  772.     {
  773.         void* pObj = NULL;
  774.         if (m_pViewPortSiteMap->Lookup(pszViewPort, pObj) && pObj)
  775.         {
  776.             // Get the site
  777.             IHXSite* pSite = (IHXSite*) pObj;
  778.             // Do a hide on the site
  779.             showSite(pSite, FALSE);
  780.             // Clear the return value
  781.             retVal = HXR_OK;
  782.         }
  783.     }
  784.     return retVal;
  785. }
  786. STDMETHODIMP CSmilDocumentRenderer::OnViewPortFocus(const char* pszViewPort)
  787. {
  788.     HX_RESULT retVal = HXR_OK;
  789.     return retVal;
  790. }
  791. STDMETHODIMP CSmilDocumentRenderer::OnViewPortZOrder(const char* pszViewPort, UINT32 ulZOrder)
  792. {
  793.     HX_RESULT retVal = HXR_OK;
  794.     return retVal;
  795. }
  796. #endif // #ifdef XXXMEH_DO_VIEWPORT_TLC
  797. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  798. BOOL
  799. CSmilDocumentRenderer::draw(HXxEvent* pEvent, IHXSite* pSite, 
  800.     UINT32 ulBgColor)
  801. {
  802.     if(pEvent &&
  803.        pEvent->event == HX_SURFACE_UPDATE && 
  804.        pEvent->result == HXR_OK)
  805.     {
  806.         // Set up color
  807.         UINT32 ulColor = ulBgColor;
  808.         // Set up bitmap info header
  809.         HXBitmapInfoHeader cHeader;
  810.         cHeader.biSize          = 40;
  811.         cHeader.biWidth         = 1;
  812.         cHeader.biHeight        = 1;
  813.         cHeader.biPlanes        = 1;
  814.         cHeader.biBitCount      = 32;
  815.         cHeader.biCompression   = (ulBgColor & 0xFF000000 ? HX_ARGB : HX_RGB);
  816.         cHeader.biSizeImage     = 0;
  817.         cHeader.biXPelsPerMeter = 0;
  818.         cHeader.biYPelsPerMeter = 0;
  819.         cHeader.biClrUsed       = 0;
  820.         cHeader.biClrImportant  = 0;
  821.         cHeader.rcolor          = 0;
  822.         cHeader.gcolor          = 0;
  823.         cHeader.bcolor          = 0;
  824.         // Set up src rect
  825.         HXxRect cSrcRect = {0, 0, 1, 1};
  826.         // Set up dst rect
  827.         HXxSize cSize = {0, 0};
  828.         pSite->GetSize(cSize);
  829.         HXxRect cDstRect = {0, 0, cSize.cx, cSize.cy};
  830.         // Do the blt
  831.         IHXVideoSurface* pSurf = (IHXVideoSurface*) pEvent->param1;
  832.         if(pSurf)
  833.         {
  834.             pSurf->AddRef();
  835.             pEvent->result = pSurf->Blt((BYTE*) &ulColor,
  836.                                         &cHeader,
  837.                                         cDstRect,
  838.                                         cSrcRect);
  839.             pSurf->Release();
  840.         }
  841.     }
  842.     return TRUE;
  843. }
  844. /*
  845.  * IHXRendererAdviseSink methods
  846.  */
  847. STDMETHODIMP
  848. CSmilDocumentRenderer::TrackDurationSet(UINT32 ulGroupIndex,
  849. UINT32 ulTrackIndex,
  850. UINT32 ulDuration,
  851. UINT32 ulDelay,
  852. BOOL bLiveSource)
  853. {
  854.     MLOG_SRC(m_pErrorMessages,"TrackDurationSet(%lu,%lu,%lu,%lu,%lu) m_ulCurrentTime=%lun",
  855.              ulGroupIndex,
  856.              ulTrackIndex,
  857.              ulDuration,
  858.              ulDelay,
  859.              bLiveSource,
  860.              m_ulCurrentTime);
  861.     HX_RESULT retVal = HXR_OK;
  862.     // /This is needed for fixing PR 66391, so we don't remove a track while
  863.     // core is still setting it up:
  864.     m_bInTrackDurationSetCall = TRUE;
  865.     SMILPlayToAssoc* pPlayToAssoc = getPlayToAssoc((UINT16)ulGroupIndex,
  866.    (UINT16)ulTrackIndex);
  867. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUG_HANDLESOURCE_AND_TRACKDURATIONSET)
  868. if (!pPlayToAssoc)
  869. {
  870.     {FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+"); ::fprintf(f1, "TrackDurationSet(media id=%s, duration=%lu, delay=%lun",
  871. "---####--NULL playToAssoc--####----", ulDuration, ulDelay);::fclose(f1);}
  872. }
  873. #endif
  874.     // /XXXEH- talk to Core dudes about this:
  875. #define TRACKDURSET_INDEFDURATION_FUDGE_FACTOR   1000 /*milliseconds*/
  876.     // /Work-around for Mac PR 81141: core is not giving us the duration we
  877.     // requested (namely WAY_IN_THE_FUTURE) on the Mac; it's returning
  878.     // 1981341952 instead of 1981342000 (i.e., is 48 millisecs too small,
  879.     // probably due to rounding error).  Let's adjust if so:
  880.     if (ulDuration > WAY_IN_THE_FUTURE)
  881.     {
  882. if (ulDuration - WAY_IN_THE_FUTURE < TRACKDURSET_INDEFDURATION_FUDGE_FACTOR)
  883. {
  884.     ulDuration = WAY_IN_THE_FUTURE;
  885. }
  886.     }
  887.     else // /ulDuration < WAY_IN_THE_FUTURE
  888.     {
  889. if (WAY_IN_THE_FUTURE - ulDuration < TRACKDURSET_INDEFDURATION_FUDGE_FACTOR)
  890. {
  891.     ulDuration = WAY_IN_THE_FUTURE;
  892. }
  893.     }
  894.     if(pPlayToAssoc)
  895.     {
  896. ULONG32 ulDurToUseForGroup = ulDuration;
  897. CSmilElement* pThisElement = 
  898. m_pSmilParser->findElement(pPlayToAssoc->m_id);
  899. #if defined(_DEBUG)  &&  defined(XXXEH_DEBUG_HANDLESOURCE_AND_TRACKDURATIONSET)
  900. {FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+"); ::fprintf(f1, "TrackDurationSet(media id=%s, duration=%lu, delay=%lun",
  901. (const char*)pPlayToAssoc->m_id, ulDuration, ulDelay);::fclose(f1);}
  902. #endif
  903. if (!pPlayToAssoc->m_bDurationResolved)
  904. {
  905.     BOOL bAlreadyHandledAsDiscreteMedia = FALSE;
  906.     
  907.     if (!pPlayToAssoc->m_bIsPersistentSource)
  908.     {
  909. #if defined(HANDLE_DISCRETE_MEDIA_IN_TrackDurationSet)
  910.     // /First, let's see if this is discrete media that needs to have
  911.     // its duration reset to 0:
  912.     BOOL bIsDiscreteImageMedia = FALSE;
  913.     BOOL bIsDiscreteTextMedia  = FALSE;
  914.     IHXBuffer* pIntrinsicDurType = NULL;
  915.     IHXStreamSource* pStreamSource = NULL;
  916.     UINT32 ulStreamHeaderDuration = 0;
  917.     const char* pszStreamMimeType = NULL;
  918.     HX_RESULT pnrIntrDurTypeRet = HXR_FAIL;
  919.     HX_RESULT pnrStrmHdrDurationRet = HXR_FAIL;
  920.     IHXGroup* pGroup = NULL;
  921.     // /Adjust for min
  922.     if (pThisElement)
  923.     {
  924. if ((UINT32)-1 != pThisElement->m_ulMinActiveDur)
  925. {
  926.     if (ulDurToUseForGroup < pThisElement->m_ulMinActiveDur)
  927.     {
  928. ulDurToUseForGroup = pThisElement->m_ulMinActiveDur;
  929.     }
  930. }
  931. if ((UINT32)-1 != pThisElement->m_ulMaxActiveDur)
  932. {
  933.     if (ulDurToUseForGroup > pThisElement->m_ulMaxActiveDur)
  934.     {
  935. ulDurToUseForGroup = pThisElement->m_ulMaxActiveDur;
  936.     }
  937. }
  938.     }
  939.     // /If it's not live and it has no authored dur (explicitly-
  940.     // set dur, end, min) then see if it's "discrete media" and,
  941.     // if so, set its duration to 0:
  942.     if(!bLiveSource  &&  pThisElement  &&
  943.     (UINT32)-1 == pThisElement->m_ulAuthoredDur  &&
  944.     // /Fixes PR 54282: if end is a sync-arc, m_ulAuthoredDur
  945.     // is not ever set to (end-begin) so we would erroneously
  946.     // treat this (img or text) as discrete media even though
  947.     // it *does* have an explicit end. (Used to work 5/11!?)
  948.     !pThisElement->m_bHasExplicitEnd  &&
  949.     0 == pThisElement->m_ulMinActiveDur  &&
  950.     m_pGroupMap  &&
  951.     m_pGroupMap->Lookup((UINT16)ulGroupIndex,(void*&)pGroup))
  952.     {
  953. IHXTrack* pTrack = NULL;
  954. IHXGroup2* pGroup2 = NULL;
  955. HX_RESULT pGrp2Rslt = pGroup->QueryInterface(IID_IHXGroup2,
  956. (void**)&pGroup2);
  957. // /This AddRef()s pTrack so be sure to release it when done:
  958. if (HXR_OK==pGrp2Rslt   &&  HXR_OK==pGroup2->GetIHXTrack(
  959. (UINT16)ulTrackIndex, pTrack))
  960. {
  961.     if (HXR_OK == pTrack->GetSource(pStreamSource)  &&
  962.     pStreamSource)
  963.     {
  964. UINT16 uNumStreams = pStreamSource->GetStreamCount();
  965. IHXStream* pStream = NULL;
  966. IHXValues* pStreamHeader = NULL;
  967. // /Use stream #0:
  968. IUnknown* pUnk = NULL;
  969. if (uNumStreams >= 1)
  970. {
  971.     pStreamSource->GetStream(0, pUnk);
  972.     HX_ASSERT(pUnk);
  973.     if (HXR_OK == pUnk->QueryInterface(IID_IHXStream,
  974.     (void**)&pStream) )
  975.     {
  976. pszStreamMimeType = pStream->GetStreamType();
  977. pStreamHeader = pStream->GetHeader();
  978. if (pStreamHeader)
  979. {
  980.     pnrIntrDurTypeRet =
  981.        pStreamHeader->GetPropertyCString(
  982.        "intrinsicDurationType",
  983.        pIntrinsicDurType);
  984. }
  985.     }
  986. }
  987. // /We don't want to handle discrete media that's one
  988. // of multiple streams in a track since it will take
  989. // on the dur of the other streams so leave it alone.
  990. if (uNumStreams == 1)
  991. {
  992.     if (pStream)
  993.     {
  994. if (pStreamHeader)
  995. {
  996.     pnrStrmHdrDurationRet =
  997.        pStreamHeader->GetPropertyULONG32(
  998.        "duration",
  999.        ulStreamHeaderDuration);
  1000.     HX_ASSERT(HXR_OK ==
  1001.     pnrStrmHdrDurationRet);
  1002.     if (pszStreamMimeType  &&
  1003. 0==strcmp(pszStreamMimeType,
  1004. "application/vnd.rn-gifstream2")  ||
  1005. 0==strcmp(pszStreamMimeType,
  1006. "application/vnd.rn-gifstream3")  ||
  1007. 0==strcmp(pszStreamMimeType,
  1008. "application/vnd.rn-jpegstream")  ||
  1009. 0==strcmp(pszStreamMimeType,
  1010. "application/vnd.rn-pngstream")  ||
  1011. 0==strcmp(pszStreamMimeType,
  1012. "application/vnd.rn-jpegstream") )
  1013.     {
  1014. bIsDiscreteImageMedia = TRUE;
  1015.     }
  1016.     else if (pszStreamMimeType  &&
  1017.     0==strcmp(pszStreamMimeType,
  1018.     "text/plain"))
  1019.     {
  1020. bIsDiscreteTextMedia = TRUE;
  1021.     }
  1022. }
  1023.     }
  1024. }
  1025. HX_RELEASE(pStreamHeader);
  1026. HX_RELEASE(pStream);
  1027. HX_RELEASE(pUnk);
  1028.     }
  1029. #define XXXEH_HACK_TO_GET_AROUND_CORE_BAD_CURRENTGROUP_IN_GetSourceInfo
  1030. #if defined(XXXEH_HACK_TO_GET_AROUND_CORE_BAD_CURRENTGROUP_IN_GetSourceInfo)
  1031. // /XXXEH- This happens in SMIL 2.0 Structure Interop test case #1.1:
  1032. // this is what's failing in the core that got us here; m_nCurrentGroup
  1033. // is sometimes 1 and sometimes (erroneously) 0:
  1034. /*HXPlayer::GetSourceInfo(...)
  1035. {
  1036. ...
  1037.     if (uGroupIndex != m_nCurrentGroup)
  1038.     {
  1039. */
  1040.     // /XXXEH- treat as discrete image for interop:
  1041.     else if(5000 == ulDuration)
  1042.     {
  1043. HX_ASSERT(0);
  1044. bIsDiscreteImageMedia = TRUE;
  1045. ulStreamHeaderDuration = 5000;
  1046.     }
  1047. #endif
  1048. }
  1049. HX_RELEASE(pTrack);
  1050. HX_RELEASE(pGroup2);
  1051. // /If the stream declared itself as discrete media and there
  1052. // is no dur, end, max, ...etc. attribute on the media
  1053. // element that overrides its intrinsic duration, then we
  1054. // should use 0s for its duration even if the stream header
  1055. // says otherwise.  This allows new file formats to stream to
  1056. // old renderers and vice versa, without breaking old content
  1057. // or having new SMIL content behave differently depending on
  1058. // the version of the discrete media file format:
  1059. BOOL bIsDiscreteMedia = FALSE;
  1060. if (HXR_OK == pnrIntrDurTypeRet  &&  pIntrinsicDurType)
  1061. {
  1062.     const char* pIntrDurBuf =
  1063.     (const char*)pIntrinsicDurType->GetBuffer();
  1064.     if (pIntrDurBuf  &&  0==strcmp(pIntrDurBuf,
  1065.     "intrinsicDurationDiscrete"))
  1066.     {
  1067. bIsDiscreteMedia = TRUE;
  1068.     }
  1069. }
  1070. // /else is undeclared, so assume non-discrete media
  1071. // unless the duration is exactly 5000msec and the stream
  1072. // mime type is that of a discrete media type (gif, jpg,
  1073. // png, plain text):
  1074. else
  1075. {
  1076.     const char* pStreamURL = NULL;
  1077.     // /We shouldn't be here if this is NULL:
  1078.     // /     HX_ASSERT(pStreamSource);
  1079.     if (pStreamSource)
  1080.     {
  1081. pStreamURL = pStreamSource->GetURL();
  1082.     }
  1083.     if (5000+ulDelay == ulStreamHeaderDuration  &&
  1084.     (UINT32)-1 == pThisElement->m_ulAuthoredDur)
  1085.     {
  1086. // /For testing only; does ulDuration include
  1087. // delay?  If so, we need to adjust for delay...:
  1088. HX_ASSERT(5000+ulDelay == ulDuration);
  1089. if (bIsDiscreteImageMedia)
  1090. {
  1091.     bIsDiscreteMedia = TRUE;
  1092. }
  1093. else if (pStreamURL)
  1094. {
  1095.       const char* pTmp = (const char*)pStreamURL;
  1096.     LONG32 lLen = strlen(pStreamURL);
  1097.     if (lLen > 4)
  1098.     {
  1099. pTmp = pTmp + (lLen-4);// /4==len(".foo")
  1100. if (0==strcmp(pTmp, ".gif")  ||
  1101. 0==strcmp(pTmp, ".jpg")  ||
  1102. 0==strcmp(pTmp, ".png") )
  1103. {
  1104.     bIsDiscreteMedia = TRUE;
  1105.     // /For testing, let's make sure that
  1106.     // we always have an image mime type
  1107.     // when we simultaneously have an
  1108.     // image extension:
  1109.     HX_ASSERT(bIsDiscreteImageMedia);
  1110. }
  1111.     }
  1112. }
  1113.     }
  1114.     else if (60000+ulDelay == ulStreamHeaderDuration  &&
  1115.     (UINT32)-1 == pThisElement->m_ulAuthoredDur)
  1116.     {
  1117. // /For testing only; does ulDuration include
  1118. // delay?  If so, we need to adjust for delay...:
  1119. HX_ASSERT(60000+ulDelay == ulDuration);
  1120. if (bIsDiscreteTextMedia)
  1121. {
  1122.     bIsDiscreteMedia = TRUE;
  1123. }
  1124. // /Might be old RealText-served .txt file with
  1125. // the RealText stream mime type:
  1126. else
  1127. {
  1128.       const char* pTmp = (const char*)pStreamURL;
  1129.     LONG32 lLen = strlen(pTmp);
  1130.     if (lLen > 4)
  1131.     {
  1132. pTmp = pTmp + (lLen-4);// /4==len(".txt")
  1133. if (0==strcmp(pTmp, ".txt"))
  1134. {
  1135.     bIsDiscreteMedia = TRUE;
  1136. }
  1137.     }
  1138. }
  1139.     }
  1140. }
  1141. if (bIsDiscreteMedia)
  1142. {
  1143.     bAlreadyHandledAsDiscreteMedia = TRUE;
  1144.     pPlayToAssoc->m_bDurationResolved = TRUE;
  1145.     pPlayToAssoc->m_ulDelay = ulDelay;
  1146.     // /Sets it so parent will use 0 dur:
  1147.     // /Note: this used to subtract the ulDelay but that was
  1148.     // totally messed up since *THIS* particular duration
  1149.     // variable does not account for the delay (unlike other
  1150.     // duration variables used in our system).  Removing that
  1151.     // fixes the last part of SMIL 2.0 Interop Timing case
  1152.     // 1.15 (at least it lets the second image show up) and
  1153.     // fixes a whole slew of SMIL 2.0 Interop Transition
  1154.     // cases including 1.1 and 1.2:
  1155.     ulDuration = ZERO_DUR; 
  1156.     BOOL bDurationIncludesDelay = FALSE;
  1157.     BOOL bResetDurationHandled = FALSE;
  1158.     // /If this had a repeatDur, repeatCount, or repeat on
  1159.     // it, we need to set its seq-for-repeat-wrapper
  1160.     // parent's dur to 0 (or 1?); get syncAncestor and then
  1161.     // see if its m_bIsSeqWrapperForRepeatElement is TRUE:
  1162.     SMILNode* pSyncAncestor = NULL;
  1163.     if (pThisElement  &&  pThisElement->m_pNode)
  1164.     {
  1165. pSyncAncestor = m_pSmilParser->getSyncAncestor(
  1166. pThisElement->m_pNode);
  1167. if (pSyncAncestor  &&
  1168.       pSyncAncestor->m_bIsSeqWrapperForRepeatElement)
  1169. {
  1170.     if (pSyncAncestor->m_pElement)
  1171.     {
  1172. UINT32 ulPriorPureDuration =
  1173. pThisElement->getPureDuration();
  1174. if (ZERO_DUR == ulPriorPureDuration)
  1175. {   // /Don't send same value as prior:
  1176.     ulPriorPureDuration++;
  1177. }
  1178. // /XXXEH- use 1 (not 0) to keep core happy:
  1179. m_pSmilParser->resetTimelineElementDuration(
  1180. pSyncAncestor->m_id, ZERO_DUR,
  1181. ulPriorPureDuration);
  1182. bResetDurationHandled = TRUE;
  1183.      m_pSmilParser->durationResolved(
  1184. pSyncAncestor->m_id, ZERO_DUR, TRUE);
  1185.     }
  1186. }
  1187.     }
  1188.     // /HOWEVER (see note about not adding delay to duration,
  1189.     // above), we need to add beginOffset to duration, but
  1190.     // ONLY if it's set to a valid value above 0:
  1191.     if (pThisElement  &&  pThisElement->m_pNode)
  1192.     {
  1193. if (pThisElement->m_bBeginOffsetSet  &&
  1194. pThisElement->m_lBeginOffset > 0)
  1195. {
  1196.     ulDuration += ulDelay;
  1197.     bDurationIncludesDelay = TRUE;
  1198. }
  1199.     }
  1200.     // /To fix PR 79748 (broken on 20010307 when ulDelay was
  1201.     // no longer subtracted from ulDuration, here), we need
  1202.     // to subtract the ulDelay once again (as we did prior to
  1203.     // 20010307) to send the pure duration to
  1204.     // durationResolved() which in turn calls
  1205.     // CSmilTimelineElement::setDuration() which assumes
  1206.     // the duration passed to it doesn't include the syncbase
  1207.     // offset.  The "broken" file that got fixed on 20010307,
  1208.     // called "...discrete_media_with_begin_offset_causes_...",
  1209.     // still works with this reversion, so something in the
  1210.     // core must have been fixed since.  20010307 bug was an
  1211.     // infinite loop in core for which this was a work-around:
  1212.     pPlayToAssoc->m_ulDuration = ulDuration -
  1213.     // /Helps fix PR 82119, by only subtracting the
  1214.     // delay if we know it's been added, above:
  1215.     (bDurationIncludesDelay? ulDelay : 0);
  1216.     HX_ASSERT(pThisElement->m_ulDuration == pThisElement->getPureDuration());
  1217.          m_pSmilParser->durationResolved(pPlayToAssoc->m_id,
  1218.     pPlayToAssoc->m_ulDuration);
  1219.     if (!bResetDurationHandled) // /Don't call reset twice:
  1220.     {
  1221. UINT32 ulPriorPureDuration = pThisElement->getPureDuration();
  1222. if (pPlayToAssoc->m_ulDuration == ulPriorPureDuration)
  1223. {   // /Don't send same value as prior:
  1224.     ulPriorPureDuration++;
  1225. }
  1226. m_pSmilParser->resetTimelineElementDuration(
  1227. pPlayToAssoc->m_id,
  1228. pPlayToAssoc->m_ulDuration, ulPriorPureDuration);
  1229.     }
  1230.     handleElements();
  1231. }
  1232. HX_RELEASE(pIntrinsicDurType);
  1233. HX_RELEASE(pStreamSource);
  1234.     }
  1235. #endif /* HANDLE_DISCRETE_MEDIA_IN_TrackDurationSet */
  1236.     }
  1237.     if (!bAlreadyHandledAsDiscreteMedia)
  1238.     {
  1239. SMILNode* pSyncBaseNode = NULL;
  1240. ULONG32 ulDelayBeyondSyncBase = 0;
  1241. BOOL bAdjustedDurForPartialPlayFactor = FALSE;
  1242. // /Had to add this now that external media markers are
  1243. // causing playToAssoc's id to be something like
  1244. // "xmmf_0x0..."
  1245. if (pThisElement)
  1246. {
  1247.     // /Part of fix for PR 57230; SMIL element needs to keep
  1248.     // track of whether or not it's live so its 0 dur won't
  1249.     // be used to compute its end time:
  1250.     if (bLiveSource)
  1251.     {
  1252. HX_ASSERT(pPlayToAssoc->m_bLiveSource);
  1253. pThisElement->m_bCurrentSourceIsLive = TRUE;
  1254.     }
  1255.     // /Fixes PR 54251:
  1256.     // /If partialPlayFactor is < 1.0 and this is not a repeat
  1257.     // element (i.e., initial partial play factor is < 1.0),
  1258.     // and if min is not constraining the lower end,
  1259.     // then multiply the ulDuration by this factor:
  1260.     if (pThisElement->m_pNode->m_fPartialPlayFactor < 1.0  &&
  1261.     (UINT32)-1 == pThisElement->m_ulDuration  &&     
  1262.     ulDurToUseForGroup >
  1263.     pThisElement->m_ulMinActiveDur)
  1264.     {
  1265. double fDur = double(float(ulDuration - ulDelay));
  1266. fDur *= pThisElement->m_pNode->m_fPartialPlayFactor;
  1267. ULONG32 ulDurTmp = ULONG32(float(fDur)) + ulDelay;
  1268. if (ulDurTmp < ulDurToUseForGroup)
  1269. {
  1270.     ulDurToUseForGroup = ulDurTmp;
  1271.     if (pThisElement->m_ulMinActiveDur >
  1272.     ulDurToUseForGroup)
  1273.     {
  1274. ulDurToUseForGroup =
  1275. pThisElement->m_ulMinActiveDur;
  1276.     }
  1277.     bAdjustedDurForPartialPlayFactor = TRUE;
  1278. }
  1279.     }
  1280.     pSyncBaseNode = m_pSmilParser->getSyncAncestor(
  1281.     pThisElement->m_pNode);
  1282.     if (!pSyncBaseNode  ||  !pSyncBaseNode->m_pElement)
  1283.     {
  1284. HX_ASSERT(pSyncBaseNode  &&  pSyncBaseNode->m_pElement);
  1285. pSyncBaseNode = pThisElement->m_pNode->m_pParent;
  1286.     }
  1287.     HX_ASSERT(ulDelay <= pThisElement->m_ulDelay);
  1288.     ulDelayBeyondSyncBase = pThisElement->m_ulDelay -
  1289.     pSyncBaseNode->m_pElement->m_ulDelay;
  1290.     // /Hold on, though: in a seq, the true "sync base" is
  1291.     // actually the prior sibling's end, not the begin of the
  1292.     // time container, i.e, sync ancestor, (unless there is
  1293.     // no prior sibling) so we don't want to use the whole
  1294.     // delay from the parent in that case (just the begin
  1295.     // offset part of this delay):
  1296.     if (SMILSeq == pSyncBaseNode->m_tag)
  1297.     {
  1298. ulDelayBeyondSyncBase = 0;
  1299. if (pThisElement->m_bBeginOffsetSet)
  1300. {
  1301.     ulDelayBeyondSyncBase =
  1302.     (pThisElement->m_lBeginOffset > 0 ?
  1303.     (UINT32)pThisElement->m_lBeginOffset : 0);
  1304. }
  1305.     }
  1306. }
  1307. pPlayToAssoc->m_bDurationResolved = TRUE;
  1308. pPlayToAssoc->m_ulDelay = ulDelay;
  1309.                 // If the value of the element duration has
  1310.                 // changed since we called AddTrack (AND, for
  1311.                 // now, we have an explicit end), then don't use
  1312.                 // the duration that came in through TrackDurationSet().
  1313.                 // Rather, use the newer value of m_ulDuration that
  1314.                 // is already in the element.
  1315.                 if (pThisElement->m_ulDuration != pThisElement->m_ulDurationInAddTrack &&
  1316.                     pThisElement->m_bHasExplicitEnd)
  1317.                 {
  1318.                     // Use the element duration instead
  1319.                     pPlayToAssoc->m_ulDuration = pThisElement->m_ulDuration;
  1320.     // /NOTE: PR 63622 content's Superman logo plays from 5s to 62s as it
  1321.     // should when it performs the above even though
  1322.     // pThisElement->getPureDuration() != pPlayToAssoc->m_ulDuration.
  1323.     // Could be a hide-site thing, i.e., if you assign above to
  1324.     // pure dur instead, hide (and not media end) could be all
  1325.     // that's happening early.
  1326.                 }
  1327.                 else
  1328.                 {
  1329.                     // Do what we've always done
  1330.                     pPlayToAssoc->m_ulDuration =
  1331.                         ulDurToUseForGroup > ulDelay ? ulDurToUseForGroup - ulDelay : 0;
  1332.     HX_ASSERT(!pThisElement->m_bDurationIncludesDelayBeyondSyncbase);
  1333.                 }
  1334. // /But wait!  If track has a delay that is greater than
  1335. // the parent delay, we want to use that difference added
  1336. // to the duration:
  1337. if (ulDelayBeyondSyncBase > 0)
  1338. {
  1339.     // /XXXEH- I need to figure out if there is ever a case
  1340.     // where the element is delayed beyond its parent and
  1341.     // has a begin offset that is *not* equal to this delay:
  1342.     HX_ASSERT(pThisElement->m_bBeginOffsetSet?
  1343.     (INT32)ulDelayBeyondSyncBase ==
  1344.     pThisElement->m_lBeginOffset: 1);
  1345.     pThisElement->m_bCurBeginIsOffsetFromSyncBase = TRUE;
  1346.     pThisElement->m_ulBeginOffsetFromSyncBase =
  1347.     ulDelayBeyondSyncBase;
  1348.     if ((UINT32)-1 != pThisElement->m_ulDuration  &&
  1349.     pThisElement->m_ulDuration > pPlayToAssoc->m_ulDuration)
  1350.     {
  1351. pThisElement->m_bDurationIncludesDelayBeyondSyncbase=TRUE;
  1352. // /Weird: I'm getting here even though if() checks for this:
  1353. HX_ASSERT((UINT32)-1 != pThisElement->m_ulDuration);
  1354. HX_ASSERT(ulDelayBeyondSyncBase ==
  1355. pThisElement->m_ulDuration -
  1356. pPlayToAssoc->m_ulDuration  &&  "ehodge");
  1357.     }
  1358.     // /NOTE: I got rid of logic here that "fixed"
  1359.     // SMIL 2.0 Interop Timing #18.7.  The right place for
  1360.     // that logic is in the subsequent call to
  1361.     // CSmilTimelineElement::setDuration(), where
  1362.     // logic has existed for a while to deal with the case
  1363.     // where the duration doesn't yet include the delay.  In
  1364.     // *this* function we're in now, we treat every begin the
  1365.     // same: the duration passed to durationResolved now
  1366.     // *never* includes the delay.
  1367. }
  1368. // /If an external marker file is the "track", here, then
  1369. // it's not really a valid track (does not partake in the
  1370. // timeline) so it doesn't have an associated CSmilElement
  1371. // and should not cause the timeline to be extended if its
  1372. // duration is longer than the others in its group:
  1373. if (!pThisElement)
  1374. {
  1375.     // /Make it 1 millisecond:
  1376.     pPlayToAssoc->m_ulDuration = 1;
  1377. }
  1378. if(bLiveSource &&
  1379.     pPlayToAssoc->m_ulDuration == 0)
  1380. {
  1381.     // don't resolve duration
  1382. }
  1383. else
  1384. {
  1385.     if (bAdjustedDurForPartialPlayFactor)
  1386.     {
  1387. // /XXXEH- This needs to be looked at, since all other
  1388. // cases (post-PR-79699 fix) use pure, delay-free
  1389. // durations for resetTimelineElementDuration():
  1390. UINT32 ulNewDuration = pPlayToAssoc->m_ulDuration +
  1391. // /Ultimately, handleSourceUpdate() gets
  1392. // called which expects the delay (beyond
  1393. // the parent begin, not the total delay) to
  1394. // be built-in to the duration:
  1395. ulDelayBeyondSyncBase;
  1396. HX_ASSERT(ulNewDuration == pThisElement->getPureDuration());
  1397. UINT32 ulPriorPureDuration = pThisElement->getPureDuration();
  1398. if (ulNewDuration == ulPriorPureDuration)
  1399. {   // /Don't send same value as prior:
  1400.     ulPriorPureDuration++;
  1401. }
  1402. m_pSmilParser->resetTimelineElementDuration(
  1403. pPlayToAssoc->m_id, ulNewDuration,
  1404. ulPriorPureDuration);
  1405.     }
  1406.     HX_ASSERT(pThisElement->m_ulDuration == pThisElement->getPureDuration());
  1407.          m_pSmilParser->durationResolved(pPlayToAssoc->m_id,
  1408.     pPlayToAssoc->m_ulDuration);
  1409. }
  1410. handleElements();
  1411.     }
  1412. }
  1413. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  1414.         // Check to see if this element has any children
  1415.         // which extend past the end of this track.
  1416.         checkAnimChildren(pThisElement, ulDuration);
  1417. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  1418. SMILGroupInfo* pGroupInfo = NULL;
  1419. if(m_pGroupInfoMap->Lookup(ulGroupIndex, (void*&)pGroupInfo) &&
  1420.    !pGroupInfo->m_bDurationSet)
  1421. {
  1422.     if (ulDurToUseForGroup >
  1423.     // /Changing this from pGroupInfo->m_ulDuration to
  1424.     // m_ulCurGroupDuration fixes PR 56686:
  1425.     m_ulCurGroupDuration) // /was:  pGroupInfo->m_ulDuration)
  1426.     {
  1427. // duration is the end of group
  1428. pGroupInfo->m_ulDuration = ulDurToUseForGroup;
  1429.     }
  1430.     if (pGroupInfo->m_ulDuration < m_ulCurGroupDuration)
  1431.     {
  1432. pGroupInfo->m_ulDuration = m_ulCurGroupDuration;
  1433.     }
  1434.     // keep tracking the duration set calls so that
  1435.     // we can notify the parent persistent renderer upon
  1436.     // the resolvement of its duration
  1437.     pGroupInfo->m_nTrackDurationsSet++;
  1438.     if (pGroupInfo->m_nTrackDurationsSet == pGroupInfo->m_nTracks)
  1439.     {
  1440. pGroupInfo->m_bDurationSet = TRUE;
  1441. ignoreLastHideEvent(ulGroupIndex, pGroupInfo);
  1442.                 // XXXMEH - if duration due to animations is longer than
  1443.                 // the group duration, then we need to up the duration
  1444.                 if (m_ulAnimDuration > pGroupInfo->m_ulDuration)
  1445.                 {
  1446.                     // First update the group duration
  1447.                     pGroupInfo->m_ulDuration = m_ulAnimDuration;
  1448.                     // Now update the "persistent layout stream duration"
  1449.                     if (m_pPersistentLayoutStream)
  1450.                     {
  1451.                         IHXValues* pStreamProps = NULL;
  1452.                         m_pPersistentLayoutStream->GetProperties(pStreamProps);
  1453.                         if (pStreamProps)
  1454.                         {
  1455.                             pStreamProps->SetPropertyULONG32("duration", m_ulAnimDuration);
  1456.                             m_pPersistentLayoutStream->SetProperties(pStreamProps);
  1457.                         }
  1458.                         HX_RELEASE(pStreamProps);
  1459.                     }
  1460.                 }
  1461. PersistentDurationSet(pGroupInfo->m_ulDuration,
  1462.       m_pSmilParser->m_ulPersistentComponentDelay,
  1463.       bLiveSource);
  1464.     }
  1465. }
  1466. retVal = HXR_OK;
  1467. goto cleanup;
  1468.     }
  1469.     else // /Failed: no pPlayToAssoc
  1470.     {
  1471. retVal = HXR_FAILED;
  1472.     }
  1473. cleanup:
  1474.     m_bInTrackDurationSetCall = FALSE;
  1475.     return retVal;
  1476. }
  1477. HX_RESULT CSmilDocumentRenderer::ignoreLastHideEvent(UINT32         ulGroupIndex,
  1478.                                                     SMILGroupInfo* pGroupInfo)
  1479. {
  1480.     HX_RESULT retVal = HXR_OK;
  1481. #if 1
  1482.     if (pGroupInfo &&
  1483.         pGroupInfo->m_bDurationSet &&
  1484.         m_pEventList)
  1485.     {
  1486.         LISTPOSITION pos = m_pEventList->GetHeadPosition();
  1487.         while (pos)
  1488.         {
  1489.             CSmilLayoutEvent* pEvent =
  1490.                 (CSmilLayoutEvent*) m_pEventList->GetNext(pos);
  1491.             if (pEvent &&
  1492.                 pEvent->m_type == CSmilLayoutEvent::eHideSite)
  1493.             {
  1494.                 CSmilShowSiteEvent* pHideEvent = (CSmilShowSiteEvent*) pEvent;
  1495.                 // Does this media have fill="remove"?
  1496.                 FillType eFill = getMediaFillBehavior((const char*) pHideEvent->getMediaID());
  1497.                 // If our remove event is scheduled for the group
  1498.                 // duration and we don't have fill="remove" behavior,
  1499.                 // then set the flag to ignore the hide event.
  1500.                 if (pEvent->m_uGroupIndex == (UINT16) ulGroupIndex &&
  1501.                     pEvent->m_ulEventTime >= pGroupInfo->m_ulDuration &&
  1502.                     eFill                 != FillRemove)
  1503.                 {
  1504.                     pEvent->m_bIgnorEvent = TRUE;
  1505.                 }
  1506.             }
  1507.         }
  1508.     }
  1509. #else
  1510.     if (pGroupInfo->m_bDurationSet && m_pSiteInfoList)
  1511.     {
  1512.         // walk through the site info list, finding sites that end
  1513.         // at the track duration, and remove their last hide event.
  1514.         CHXSimpleList::Iterator i = m_pSiteInfoList->Begin();
  1515.         for (;i != m_pSiteInfoList->End(); ++i)
  1516.         {
  1517.             SMILSiteInfo* pSiteInfo = (SMILSiteInfo*)(*i);
  1518.             if (pSiteInfo->m_uGroupIndex == ulGroupIndex &&
  1519.                 pSiteInfo->m_ulDuration == pGroupInfo->m_ulDuration)
  1520.             {
  1521.                 // this site ends at the end of this group...
  1522.                 // remove its last hide event...
  1523.                 LISTPOSITION pos = m_pEventList->GetHeadPosition();
  1524.                 while (pos)
  1525.                 {
  1526.                     CSmilLayoutEvent* pEvent = (CSmilLayoutEvent*)
  1527.                         m_pEventList->GetAt(pos);
  1528.                     if (pEvent &&
  1529.                         pEvent->m_type == CSmilLayoutEvent::eHideSite)
  1530.                     {
  1531.                         // Cast to show site event
  1532.                         CSmilShowSiteEvent* pHideEvent = (CSmilShowSiteEvent*) pEvent;
  1533.                         // Get the fill behavior for the media
  1534.                         FillType eFill = getMediaFillBehavior((const char*) pHideEvent->getMediaID());
  1535.                         // Decide if we need to supress the hide
  1536.                         if (pEvent->m_uGroupIndex == ulGroupIndex &&
  1537.                             pEvent->m_ulEventTime == pSiteInfo->m_ulDuration &&
  1538.                             eFill                 != FillRemove)
  1539.                         {
  1540.                             pEvent->m_bIgnorEvent = TRUE;
  1541.                             break;
  1542.                         }
  1543.                     }
  1544.                     m_pEventList->GetNext(pos);
  1545.                 }
  1546.             }
  1547.         }
  1548.     }
  1549. #endif
  1550.     return retVal;
  1551. }
  1552. STDMETHODIMP
  1553. CSmilDocumentRenderer::RepeatedTrackDurationSet(const char*  pID,
  1554. UINT32 ulDuration,
  1555. BOOL   bIsLive)
  1556. {
  1557.     MLOG_SRC(m_pErrorMessages,
  1558.              "RepeatedTrackDurationSet(%s,%lu,%lu) m_ulCurrentTime=%lun",
  1559.              pID, ulDuration, bIsLive, m_ulCurrentTime);
  1560.     if(!bIsLive)
  1561.     {
  1562. m_pSmilParser->durationResolved(pID,
  1563. ulDuration);
  1564. handleElements();
  1565.     }
  1566.     return HXR_OK;
  1567. }
  1568. STDMETHODIMP
  1569. CSmilDocumentRenderer::TrackUpdated(UINT32 ulGroupIndex,
  1570.     UINT32 ulTrackIndex,
  1571.     IHXValues* pValues)
  1572. {
  1573.     HX_RESULT rc = HXR_OK;
  1574.     UINT16 uNewTrackIndex = 0;
  1575.     UINT32 ulNewTrackIndex = 0;
  1576.     SMILPlayToAssoc* pPlayToAssoc = getPlayToAssoc((UINT16)ulGroupIndex,
  1577.    (UINT16)ulTrackIndex);
  1578.     if (!pPlayToAssoc)
  1579.     {
  1580. rc = HXR_UNEXPECTED;
  1581. goto cleanup;
  1582.     }
  1583.     // /Don't cast a UINT16& to a UINT32& here otherwise Big-endian
  1584.     // machines will not receive the right 2 bytes (part of fix for
  1585.     // PR 121880; rest of fix is in client/core):
  1586.     if (HXR_OK == pValues->GetPropertyULONG32("TrackIndex", ulNewTrackIndex))
  1587.     {
  1588.         pPlayToAssoc->m_uTrackIndex = (UINT16)ulNewTrackIndex;
  1589.     }
  1590. cleanup:
  1591.     return rc;
  1592. }
  1593.   
  1594. STDMETHODIMP CSmilDocumentRenderer::AddShowEvents(const char* pRegionName,
  1595.                                                   IHXSite*   pSite)
  1596. {
  1597.     HX_RESULT rc = HXR_OK;
  1598.     SMILPlayToAssoc* pPlayToAssoc = getPlayToAssoc(pRegionName);
  1599.     if(pPlayToAssoc)
  1600.     {
  1601. showSite(pSite, FALSE);
  1602. UINT32 ulShowTime = pPlayToAssoc->m_ulDelay;
  1603. UINT32 ulRemoveTime = pPlayToAssoc->m_ulDuration + 
  1604.     pPlayToAssoc->m_ulDelay;
  1605. if (ulShowTime != ulRemoveTime)
  1606. {
  1607.             // show site after m_ulDelay
  1608.             CSmilShowSiteEvent* pShowEvent =
  1609.                 new CSmilShowSiteEvent(pPlayToAssoc->m_uGroupIndex,
  1610.                                        ulShowTime,
  1611.                                        pSite,
  1612.                                        NULL,
  1613.                                        TRUE);
  1614.     insertEvent(pShowEvent);
  1615.     
  1616. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  1617.     if (pPlayToAssoc->m_beginTransition.GetLength() > 0)
  1618.     {
  1619. CSmilTransitionEvent* pTransEvent =
  1620.     new CSmilTransitionEvent(pPlayToAssoc->m_ulDelay,
  1621.     pPlayToAssoc, pSite, TRUE, this);
  1622. insertEvent(pTransEvent);
  1623.     }
  1624. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  1625.     // hide site after m_ulDuration if it isn't live
  1626.     if(pPlayToAssoc->m_bRemoveSite &&
  1627.        !pPlayToAssoc->m_bLiveSource)
  1628.     {
  1629.                 CSmilShowSiteEvent* pHideEvent =
  1630.                     new CSmilShowSiteEvent(pPlayToAssoc->m_uGroupIndex,
  1631.                                            ulRemoveTime,
  1632.                                            pSite,
  1633.                                            NULL,
  1634.                                            FALSE);
  1635. insertEvent(pHideEvent);
  1636.                 // Set the event time into the element
  1637.                 setElementRemoveTime(pPlayToAssoc->m_id, ulRemoveTime);
  1638.     }
  1639. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  1640.     // schedule an end transition if there is one.
  1641.     if (pPlayToAssoc->m_endTransition.GetLength() > 0 &&
  1642. !pPlayToAssoc->m_bLiveSource)
  1643.     {
  1644. CSmilTransitionInfo* pTInfo = getTransition(
  1645.     pPlayToAssoc->m_endTransition);
  1646. if (pTInfo)
  1647. {
  1648.     CSmilTransitionEvent* pTransEvent =
  1649. new CSmilTransitionEvent(
  1650. pPlayToAssoc->m_ulDelay + pPlayToAssoc->m_ulDuration - pTInfo->m_pTrans->m_ulDuration,
  1651. pPlayToAssoc, pSite, FALSE, this);
  1652.     insertEvent(pTransEvent);
  1653. }
  1654.     }
  1655. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  1656. }
  1657.     }
  1658.     return rc;
  1659. }
  1660. STDMETHODIMP CSmilDocumentRenderer::SiteUserAttachSite(CSmilSiteUser* pUser, IHXSite* pSite)
  1661. {
  1662.     HX_RESULT retVal = HXR_OK;
  1663.     if (pUser && pSite)
  1664.     {
  1665.         if (m_pRootLayout &&
  1666.             m_pRootLayout->m_pSiteUser == pUser)
  1667.         {
  1668.             MLOG_LAYOUT(m_pErrorMessages,
  1669.                         "root-layout AttachSite() m_ulCurrentTime=%lu tick=%lun",
  1670.                         m_ulCurrentTime, HX_GET_BETTERTICKCOUNT());
  1671.             // Save the top-level site
  1672.             HX_RELEASE(m_pRootLayout->m_pSite);
  1673.             m_pRootLayout->m_pSite = pSite;
  1674.             m_pRootLayout->m_pSite->AddRef();
  1675.             // Create a passive site watcher object for
  1676.             // the top-level site
  1677.             HX_DELETE(m_pRootLayout->m_pPassiveSiteWatcher);
  1678.             m_pRootLayout->m_pPassiveSiteWatcher =
  1679.                 new CSmilPassiveSiteWatcher((CSmilPassiveSiteWatcherResponse*) this,
  1680.                                             m_pRootLayout->m_pSite);
  1681.             if (m_pRootLayout->m_pPassiveSiteWatcher)
  1682.             {
  1683.                 m_pRootLayout->m_pPassiveSiteWatcher->AddRef();
  1684.             }
  1685.             // Set the size of the top-level site
  1686.             setTopLevelSiteSize();
  1687.             // Clear the flag saying we've detached the root-layout site
  1688.             m_bRootLayoutSiteDetached = FALSE;
  1689.         }
  1690. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  1691.         else
  1692.         {
  1693.             // Check and see if this is a viewport
  1694.             CSmilBasicViewport* pPort = getViewportBySiteUser(pUser);
  1695.             if (pPort)
  1696.             {
  1697.                 // Save the site
  1698.                 HX_RELEASE(pPort->m_pSite);
  1699.                 pPort->m_pSite = pSite;
  1700.                 pPort->m_pSite->AddRef();
  1701.                 // Set the position
  1702.                 HXxPoint cPos = {0, 0};
  1703.                 pPort->m_pSite->SetPosition(cPos);
  1704.                 // Set the size
  1705.                 HXxSize cSize = {HXxRECT_WIDTH(pPort->m_Rect),
  1706.                                  HXxRECT_HEIGHT(pPort->m_Rect)};
  1707. #if defined(XXXMEH_DO_VIEWPORT_TLC) && defined(_WINDOWS)
  1708.                 cSize.cx += GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
  1709.                 cSize.cy += GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + 
  1710.                             GetSystemMetrics(SM_CYCAPTION);
  1711. #endif
  1712.                 pPort->m_pSite->SetSize(cSize);
  1713.                 // Create a passive site watcher object for
  1714.                 // the top-level site
  1715.                 HX_DELETE(pPort->m_pPassiveSiteWatcher);
  1716.                 pPort->m_pPassiveSiteWatcher =
  1717.                     new CSmilPassiveSiteWatcher((CSmilPassiveSiteWatcherResponse*) this,
  1718.                                                 pPort->m_pSite);
  1719.                 if (pPort->m_pPassiveSiteWatcher)
  1720.                 {
  1721.                     pPort->m_pPassiveSiteWatcher->AddRef();
  1722.                 }
  1723.                 // Now we need to finish the setup for this viewport
  1724.                 retVal = finishOneViewportSetup(pPort);
  1725.             }
  1726.         }
  1727. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  1728.     }
  1729.     else
  1730.     {
  1731.         retVal = HXR_FAIL;
  1732.     }
  1733.     return retVal;
  1734. }
  1735. STDMETHODIMP CSmilDocumentRenderer::SiteUserDetachSite(CSmilSiteUser* pUser)
  1736. {
  1737.     HX_RESULT retVal = HXR_OK;
  1738.     BOOL bNeedToRelease = FALSE;
  1739.     if (pUser)
  1740.     {
  1741.         // Determine if this is a root
  1742.         if (m_pRootLayout &&
  1743.             m_pRootLayout->m_pSiteUser == pUser)
  1744.         {
  1745.             // Destroy the renderer sites of those renderers playing
  1746.             // to regions which are under the root-layout. This also
  1747.             // deletes the corresponding site watchers as well.
  1748.             destroyRendererSites(m_pRootLayout);
  1749.             // Properly destroy the parent-child relationships - 
  1750.             // this makes sure that the proper parent calls
  1751.             // DestroyChild(), but it does not delete the CSmilBasicRegion
  1752.             // itself, since the region map owns that.
  1753.             destroyRegionSites(m_pRootLayout->m_pChildList);
  1754.     // keep the region info around so that all layout/region/renderer
  1755.     // sites can be re-created during nested meta playlist navigation
  1756.     if (m_bCloseCalled ||
  1757.                 (m_pParent && !m_pParent->m_bUseNestedMeta))
  1758.     {
  1759. // Now destroy the CSmilBasicRegion's which
  1760. // are under the root-layout
  1761. destroyRegions(m_pRootLayout->m_pChildList);
  1762.     }
  1763.             // Close the root layout's passive site watcher. This
  1764.             // causes it to release its ref on us.
  1765.             if (m_pRootLayout->m_pPassiveSiteWatcher)
  1766.             {
  1767.                 m_pRootLayout->m_pPassiveSiteWatcher->Close();
  1768.             }
  1769.             // Remove the site user as a layout group
  1770.             if (m_pRootLayout->m_pSiteUser && m_pParent)
  1771.             {
  1772.                 IUnknown* pThisUnk = NULL;
  1773.                 m_pRootLayout->m_pSiteUser->QueryInterface(IID_IUnknown, (void**) &pThisUnk);
  1774.                 if (pThisUnk)
  1775.                 {
  1776.                     m_pParent->HandleRemoveLayoutSiteGroup(pThisUnk);
  1777.                 }
  1778.                 HX_RELEASE(pThisUnk);
  1779.             }
  1780.             // Close the root layout's site user. This causes it
  1781.             // to release its ref on us. So before we do that,
  1782.             // we AddRef() ourselves and we will release ourselves
  1783.             // directly below.
  1784.             AddRef();
  1785.             bNeedToRelease = TRUE;
  1786.             // Close the root-layout's site user
  1787.             if (m_pRootLayout->m_pSiteUser)
  1788.             {
  1789.                 m_pRootLayout->m_pSiteUser->Close();
  1790.             }
  1791.             // Release the top-level site
  1792.             HX_RELEASE(m_pRootLayout->m_pSite);
  1793.             // Delete the root-layout ONLY if close
  1794.             // has been called. If close has been called, then
  1795.             // this is the last line of defense.
  1796.             if (m_bCloseCalled)
  1797.             {
  1798.                 HX_DELETE(m_pRootLayout);
  1799.             }
  1800.             // Set the flag saying we've detached the root-layout site
  1801.             m_bRootLayoutSiteDetached = TRUE;
  1802. #ifdef _MACINTOSH
  1803.             if (m_bResetCursor)
  1804.             {
  1805.                 m_bResetCursor = FALSE;
  1806.                 ::InitCursor();
  1807.             }
  1808. #endif
  1809.         }
  1810. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  1811.         else
  1812.         {
  1813.             // Is this a DetachSite() for one of the viewports?
  1814.             CSmilBasicViewport* pPort = getViewportBySiteUser(pUser);
  1815.             if (pPort)
  1816.             {
  1817.                 // Destroy the renderer sites of those renderers playing
  1818.                 // to regions which are under this viewport. This also
  1819.                 // deletes the corresponding site watchers as well.
  1820.                 destroyRendererSites(pPort);
  1821.                 // Properly destroy the parent-child relationships - 
  1822.                 // this makes sure that the proper parent calls
  1823.                 // DestroyChild(), but it does not delete the CSmilBasicRegion
  1824.                 // itself, since the region map owns that.
  1825.                 destroyRegionSites(pPort->m_pChildList);
  1826.                 // Now destroy the CSmilBasicRegion's which
  1827.                 // are under this viewport
  1828.                 destroyRegions(pPort->m_pChildList);
  1829.                 // Close this viewport's passive site watcher. This
  1830.                 // causes it to release its ref on us.
  1831.                 if (pPort->m_pPassiveSiteWatcher)
  1832.                 {
  1833.                     pPort->m_pPassiveSiteWatcher->Close();
  1834.                 }
  1835.                 // Close this viewport's site user
  1836.                 if (pPort->m_pSiteUser)
  1837.                 {
  1838.                     pPort->m_pSiteUser->Close();
  1839.                 }
  1840.                 // Release this viewport's site
  1841.                 HX_RELEASE(pPort->m_pSite);
  1842.             }
  1843.         }
  1844. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  1845.     }
  1846.     else
  1847.     {
  1848.         retVal = HXR_FAIL;
  1849.     }
  1850.     m_bSitesDetached = TRUE;
  1851.     if (bNeedToRelease)
  1852.     {
  1853.         Release();
  1854.     }
  1855.     
  1856.     return retVal;
  1857. }
  1858. STDMETHODIMP CSmilDocumentRenderer::SiteUserHandleEvent(CSmilSiteUser* pUser,
  1859.                                                         HXxEvent*      pEvent)
  1860. {
  1861.     HX_RESULT retVal = HXR_OK;
  1862.     if (pUser && pEvent)
  1863.     {
  1864.         switch (pEvent->event)
  1865.         {
  1866.             case HX_SET_FOCUS:
  1867.                 {
  1868.                     pEvent->handled = TRUE;
  1869.                 }
  1870.                 break;
  1871.             case HX_LOSE_FOCUS:
  1872.                 {
  1873.                     pEvent->handled = TRUE;
  1874.                 }
  1875.                 break;
  1876.             case HX_CHAR:
  1877.                 {
  1878.                     UINT16 uCharPressed = (UINT16) (UINT32)pEvent->param1;
  1879.                     // XXXEH: TODO: Handle this: "The character is a single
  1880.                     // character from [[ISO10646]]."
  1881.                     retVal = HandleCharEvent(uCharPressed);
  1882.                     if (SUCCEEDED(retVal))
  1883.                     {
  1884.                         // XXXMEH - we will no longer claim that we handle
  1885.                         // keystrokes. This will allow renderers such as 
  1886.                         // flash to get the keystrokes for forms, etc.
  1887.                         pEvent->handled = FALSE;
  1888.                     }
  1889.                 }
  1890.                 break;
  1891. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  1892. #ifdef XXXMEH_DO_VIEWPORT_TLC
  1893.             case HX_DETACH_WINDOW:
  1894.                 {
  1895.                     // This message could be the result of either: a) the
  1896.                     // user closing the viewport window; or b) the SMIL renderer
  1897.                     // shutting down. If this is the result of the SMIL renderer
  1898.                     // shutting down, then the SMIL renderer has ALREADY called
  1899.                     // IHXViewPortManager::CloseViewPort(), so we should not call
  1900.                     // it again. However, if this is the result of the user
  1901.                     // closing the viewport window, then we need to call 
  1902.                     // CloseViewPort.
  1903.                     if (!m_bSMILViewportClose)
  1904.                     {
  1905.                         // Are we a viewport?
  1906.                         CSmilBasicViewport* pPort = getViewportBySiteUser(pUser);
  1907.                         if (pPort && m_pViewPortManager)
  1908.                         {
  1909.                             // We are getting a viewport close, so close the viewport
  1910.                             retVal = m_pViewPortManager->CloseViewPort(pPort->m_id);
  1911.                             if (SUCCEEDED(retVal))
  1912.                             {
  1913.                                 pEvent->handled = TRUE;
  1914.                             }
  1915.                         }
  1916.                     }
  1917.                 }
  1918.                 break;
  1919. #if defined(_WINDOWS)
  1920.             case WM_SETFOCUS:
  1921.                 {
  1922.                     // Are we a viewport?
  1923.                     CSmilBasicViewport* pPort = getViewportBySiteUser(pUser);
  1924.                     if (pPort && m_pViewPortManager)
  1925.                     {
  1926.                         // Get the viewport
  1927.                         IHXViewPort* pVP = NULL;
  1928.                         retVal = m_pViewPortManager->GetViewPort(pPort->m_id, pVP);
  1929.                         if (SUCCEEDED(retVal))
  1930.                         {
  1931.                             retVal = pVP->SetFocus();
  1932.                         }
  1933.                         HX_RELEASE(pVP);
  1934.                     }
  1935.                 }
  1936.                 break;
  1937.             case WM_SIZING:
  1938.                 {
  1939.                     HXxRect cRect    = {0, 0, 0, 0};
  1940.                     LPRECT  pWinRect = (LPRECT) pEvent->param2;
  1941.                     if (pWinRect)
  1942.                     {
  1943.                         cRect.left   = pWinRect->left;
  1944.                         cRect.top    = pWinRect->top;
  1945.                         cRect.right  = pWinRect->right;
  1946.                         cRect.bottom = pWinRect->bottom;
  1947.                     }
  1948.                     // Are we a viewport?
  1949.                     CSmilBasicViewport* pPort = getViewportBySiteUser(pUser);
  1950.                     if (pPort && pPort->m_pSite)
  1951.                     {
  1952.                         HXxSize cOldSize = {0, 0};
  1953.                         pPort->m_pSite->GetSize(cOldSize);
  1954.                         HXxSize cSize = {HXxRECT_WIDTH(cRect), HXxRECT_HEIGHT(cRect)};
  1955.                         if (cSize.cx > 0 && cSize.cy > 0 &&
  1956.                             (cSize.cx != cOldSize.cx ||
  1957.                              cSize.cy != cOldSize.cy))
  1958.                         {
  1959.                             pPort->m_pSite->SetSize(cSize);
  1960.                         }
  1961.                     }
  1962.                 }
  1963.                 break;
  1964. #endif // #if defined(_WINDOWS)
  1965. #endif // #ifdef XXXMEH_DO_VIEWPORT_TLC
  1966. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  1967.             default:
  1968.                 break;
  1969.         }
  1970.         // Set the result
  1971.         if (SUCCEEDED(retVal))
  1972.         {
  1973.             pEvent->result = retVal;
  1974.         }
  1975.     }
  1976.     else
  1977.     {
  1978.         retVal = HXR_FAIL;
  1979.     }
  1980.     return retVal;
  1981. }
  1982. STDMETHODIMP
  1983. CSmilDocumentRenderer::RendererInitialized(IHXRenderer* pRenderer, 
  1984.     IUnknown* pStream, IHXValues* pInfo)
  1985. {
  1986.     HX_RESULT rc = HXR_OK;
  1987.     BOOL bIsWindowed = FALSE;
  1988.     BOOL bHandleElement = FALSE;
  1989.     HX_DISPLAY_TYPE ulFlags;
  1990.     IHXBuffer* pBuf = 0;
  1991.     if(HXR_OK == pRenderer->GetDisplayType(ulFlags, pBuf))
  1992.     {
  1993.         if (HX_DISPLAY_WINDOW == (HX_DISPLAY_WINDOW & ulFlags))
  1994. {
  1995.     bIsWindowed = TRUE;
  1996. }
  1997. HX_RELEASE(pBuf);
  1998.     }
  1999.     UINT32 ulGroupIndex      = 0;
  2000.     UINT32 ulTrackIndex      = 0;
  2001.     UINT32 ulDelay           = 0;
  2002.     UINT32 ulDuration        = 0;
  2003.     UINT32 ulLiveSource      = 0;
  2004.     pInfo->GetPropertyULONG32("GroupIndex", ulGroupIndex);
  2005.     pInfo->GetPropertyULONG32("TrackIndex", ulTrackIndex);
  2006.     pInfo->GetPropertyULONG32("Delay", ulDelay);
  2007.     // "duration" is really the end time in the current group
  2008.     pInfo->GetPropertyULONG32("Duration", ulDuration);  
  2009.     pInfo->GetPropertyULONG32("LiveSource", ulLiveSource);
  2010.     MLOG_SRC(m_pErrorMessages,"RendererInitialized() grp=%lu trk=%lu m_ulCurrentTime=%lu t=%lun",
  2011.              ulGroupIndex, ulTrackIndex, m_ulCurrentTime, HX_GET_BETTERTICKCOUNT());
  2012.     IHXBuffer* pBuffer = NULL;
  2013.     SMILPlayToAssoc* pPlayToAssoc = NULL;
  2014.     if (HXR_OK == pInfo->GetPropertyCString("id", pBuffer))
  2015.     {
  2016. pPlayToAssoc = getPlayToAssocByMedia((const char*)pBuffer->GetBuffer());
  2017.     }
  2018.     HX_RELEASE(pBuffer);
  2019.     if (!pPlayToAssoc)
  2020.     {
  2021. // XXX HP we shouldn't be here
  2022. HX_ASSERT(FALSE);
  2023. pPlayToAssoc = getPlayToAssoc((UINT16)ulGroupIndex, (UINT16)ulTrackIndex);
  2024.     }
  2025.     UINT16 uStreamNumber = 0;
  2026.     IHXStream* pStr = 0;
  2027.     if(HXR_OK == pStream->QueryInterface(IID_IHXStream,
  2028.     (void**)&pStr))
  2029.     {
  2030. uStreamNumber = pStr->GetStreamNumber();
  2031.         // Here we want to get the URL and save it
  2032.         // in the playToAssoc, so that we can look
  2033.         // it up later if necessary
  2034.         //
  2035.         // QI for IHXStreamSource
  2036.         IHXStreamSource* pStreamSource = NULL;
  2037.         pStr->GetSource(pStreamSource);
  2038.         if (pStreamSource)
  2039.         {
  2040.             if (pPlayToAssoc)
  2041.             {
  2042.                 pPlayToAssoc->m_URL = pStreamSource->GetURL();
  2043.                 // If we are a external media marker source, then
  2044.                 // we need to update our info struct with this url
  2045.                 if (pPlayToAssoc->m_bXMMSource && m_pExternalMediaMarkerList)
  2046.                 {
  2047.                     IHXBuffer* pTB = NULL;
  2048.                     pInfo->GetPropertyCString("url", pTB);
  2049.                     if (pTB)
  2050.                     {
  2051.                         HX_RELEASE(pTB);
  2052.                     }
  2053.                     LISTPOSITION pos = m_pExternalMediaMarkerList->GetHeadPosition();
  2054.                     while (pos)
  2055.                     {
  2056.                         CExternalMediaMarkerInfo* pMInfo =
  2057.                             (CExternalMediaMarkerInfo*) m_pExternalMediaMarkerList->GetNext(pos);
  2058.                         if (pMInfo &&
  2059.                             pMInfo->m_usGroupIndex == (UINT16) ulGroupIndex &&
  2060.                             pMInfo->m_usTrackIndex == (UINT16) ulTrackIndex)
  2061.                         {
  2062.                             HX_VECTOR_DELETE(pMInfo->m_pszRendererURL);
  2063.                             pMInfo->m_pszRendererURL =
  2064.     new char [pPlayToAssoc->m_URL.GetLength() + 1];
  2065.                             if (pMInfo->m_pszRendererURL)
  2066.                             {
  2067.                                 strcpy(pMInfo->m_pszRendererURL, pPlayToAssoc->m_URL); /* Flawfinder: ignore */
  2068.                                 break;
  2069.                             }
  2070.                         }
  2071.                     }
  2072.                 }
  2073.             }
  2074.         }
  2075.         HX_RELEASE(pStreamSource);
  2076. HX_RELEASE(pStr);
  2077.     }
  2078.     // /Get SMIL layout stream:
  2079.     // XXX HP the following if statement will be obsolete after using 
  2080.     //       nested meta logic since m_pPersistentLayoutStream should
  2081.     //       be set in ::InitPersistent()
  2082.     if (!m_pParent->m_bUseNestedMeta && !m_pPersistentLayoutStream)
  2083.     {
  2084. if (HXR_OK != pStream->QueryInterface(IID_IHXLayoutStream, 
  2085. (void**)&m_pPersistentLayoutStream))
  2086. {
  2087.     HX_ASSERT(m_pPersistentLayoutStream);
  2088. }
  2089.     }
  2090.     CSmilBasicRegion* pRegion = NULL;
  2091.     if(bIsWindowed)
  2092.     {
  2093.         // This is the box at which we need to
  2094.         // re-compute the z-order stack
  2095.         CSmilBasicBox* pZOrderBox = NULL;
  2096. IHXLayoutStream* pLayoutStream = NULL;
  2097. if(HXR_OK == pStream->QueryInterface(IID_IHXLayoutStream,
  2098.     (void**)&pLayoutStream))
  2099. {
  2100.     BOOL bNoRegion = TRUE;
  2101.     if(pPlayToAssoc)
  2102.     {
  2103. CHXSimpleList* pRendererList = NULL;
  2104. SMILSourceInfo* pSourceInfo = NULL;
  2105. const char* pPlayTo = pPlayToAssoc->m_playTo;
  2106. // re-create layout/region/renderer sites if
  2107. // sites have been detached upon playlist navigation
  2108. if (m_bSitesDetached)
  2109. {
  2110.     m_bSitesDetached = FALSE;
  2111.     rc = setupRootLayout(FALSE);
  2112.     HX_ASSERT(HXR_OK == rc);
  2113. }
  2114. // See if we need to layout this renderer
  2115. //
  2116. // First check to see if we have a region by id
  2117. pRegion = getRegionByID(pPlayTo);
  2118. if(pRegion)
  2119. {
  2120.     bNoRegion = FALSE;
  2121.     // We will need to recompute the z-order
  2122.     // stack of this region's parent
  2123.     pZOrderBox = getTopLevelBox(pRegion);
  2124. }
  2125. else
  2126. {
  2127.     // We didn't find it by id, so try finding
  2128.     // a region by regionName
  2129.     pRegion = getFirstRegionByName(pPlayTo);
  2130.     if (pRegion)
  2131.     {
  2132. bNoRegion = FALSE;
  2133. // We will need to recompute the z-order
  2134. // stack of this region's parent
  2135. pZOrderBox = getTopLevelBox(pRegion);
  2136.     }
  2137.     else
  2138.     {
  2139. // We didn't find a <region> by id and we 
  2140. // didn't find a <region> by the "regionName"
  2141. // indirection, so we are going to have to 
  2142. // fall back to the "default" region.
  2143. pRegion = setupDefaultLayout();
  2144. if (pRegion)
  2145. {
  2146.     // Clear the flag
  2147.     bNoRegion = FALSE;
  2148.     // Change the parameters
  2149.     pPlayToAssoc->m_playTo     = pRegion->m_region;
  2150.     pPlayToAssoc->m_regionName = pRegion->m_region;
  2151.     pPlayTo                    = (const char*) pRegion->m_region;
  2152.     // We will need to recompute the z-order
  2153.     // stack of this region's parent
  2154.     pZOrderBox = getTopLevelBox(pRegion);
  2155. }
  2156.     }
  2157. }
  2158.                 // /vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  2159.                 // /XXXEH- To do: this is same code as found inside
  2160.                 // AttachElementLayout(), below.  Combine into single function:
  2161. pSourceInfo = new SMILSourceInfo;
  2162. pSourceInfo->m_pStream = pStream;
  2163. if(pSourceInfo->m_pStream)
  2164. {
  2165.     pSourceInfo->m_pStream->AddRef();
  2166. }
  2167. pSourceInfo->m_pRenderer = pRenderer;
  2168. if(pSourceInfo->m_pRenderer)
  2169. {
  2170.     pSourceInfo->m_pRenderer->AddRef();
  2171. }
  2172. pSourceInfo->m_ulDelay = ulDelay;
  2173. pSourceInfo->m_ulDuration = ulDuration - ulDelay;
  2174. char cTemp[20]; /* Flawfinder: ignore */
  2175. ::sprintf(cTemp,"%#010lx",(ULONG32)(void*)pSourceInfo); /* Flawfinder: ignore */
  2176. pSourceInfo->m_tunerName   = (const char*) cTemp;
  2177. ::sprintf(cTemp,"%#010lx",(ULONG32)(void*)pSourceInfo+1); /* Flawfinder: ignore */
  2178. pSourceInfo->m_childTunerName = (const char*)cTemp;
  2179. const char* pChildTuner = pSourceInfo->m_childTunerName;
  2180. // get to the site manager and set an event hook
  2181. IHXEventHookMgr* pHookMgr = NULL;
  2182. if(HXR_OK ==
  2183.     m_pSiteMgr->QueryInterface(IID_IHXEventHookMgr, 
  2184.     (void**)&pHookMgr))
  2185. {
  2186.                     CSmilEventHook* pChildEventHook = NULL;
  2187.                     // create event hook for playto
  2188.                     pChildEventHook = new CSmilEventHook((CSmilEventHookResponse*) this,
  2189.                                                          pPlayTo, pChildTuner, bNoRegion,
  2190.                                                          (const char*) pPlayToAssoc->m_id);
  2191.                     pChildEventHook->AddRef();
  2192.                     pHookMgr->AddHook(pChildEventHook, pChildTuner, 0);
  2193.                     pSourceInfo->m_pRendererEventHook = pChildEventHook;
  2194.                     pHookMgr->Release();
  2195. }
  2196. else
  2197. {
  2198.     pSourceInfo->m_pRendererEventHook = NULL;
  2199. }
  2200. if (NULL == pPlayToAssoc->m_sourceMap[uStreamNumber])
  2201. {
  2202.     pPlayToAssoc->m_sourceMap[uStreamNumber] = new CHXSimpleList();
  2203.     pPlayToAssoc->m_tunerName = pSourceInfo->m_tunerName;
  2204.     pPlayToAssoc->m_childTunerName = pSourceInfo->m_childTunerName;
  2205.     pPlayToAssoc->m_ulDelay = pSourceInfo->m_ulDelay;
  2206.     pPlayToAssoc->m_ulDuration = pSourceInfo->m_ulDuration;
  2207.     pPlayToAssoc->m_bLiveSource = ulLiveSource ? TRUE : FALSE;
  2208.     pPlayToAssoc->m_pRendererEventHook = pSourceInfo->m_pRendererEventHook;
  2209.     // add hyperlinks
  2210.     CSmilElement* pElement = m_pSmilParser->findElement(
  2211. pPlayToAssoc->m_id);
  2212.     if(pElement && pElement->m_pHyperlinks)
  2213.     {
  2214. CHXSimpleList::Iterator i = 
  2215. pElement->m_pHyperlinks->Begin();
  2216. for(; i != pElement->m_pHyperlinks->End(); ++i)
  2217. {
  2218.     CSmilAAnchorElement* pAnchor = 
  2219. (CSmilAAnchorElement*)(*i);
  2220.     //[SMIL 1.0 Compliance] Fixes PR 26473:
  2221.     // We want to add in LIFO fashion so inner
  2222.     // (nested) anchors will be found first in
  2223.     // CSmilDocumentRenderer::findHyperlinkElement(),
  2224.     // below.  In other words, we're giving an
  2225.     // effective higher link "z-order" to the
  2226.     // decendants of other links.  This used to
  2227.     // call AddTail():
  2228.     pPlayToAssoc->m_pHyperlinks->AddHead(pAnchor);
  2229. }
  2230.     }
  2231.     bHandleElement = TRUE;
  2232. }
  2233. pRendererList = (CHXSimpleList*) pPlayToAssoc->m_sourceMap[uStreamNumber];
  2234. pRendererList->AddTail(pSourceInfo);
  2235. IHXValues* pValues = 0;
  2236. IHXBuffer* pPlayToBuffer = 0;
  2237. IHXBuffer* pRegionName = 0;
  2238. IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  2239. if ((HXR_OK == pFactory->CreateInstance(CLSID_IHXValues, (void**)&pValues)) &&
  2240.     (HXR_OK == pFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pPlayToBuffer)) &&
  2241.     (HXR_OK == pFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pRegionName)))
  2242. {     
  2243.     pPlayToBuffer->Set((BYTE*)pChildTuner, strlen(pChildTuner)+1);
  2244.     pValues->SetPropertyCString("playto", pPlayToBuffer);
  2245.     HX_RELEASE(pPlayToBuffer);
  2246.     if(pPlayToAssoc->m_regionName.GetLength() > 0)
  2247.     {
  2248. const char* pName = pPlayToAssoc->m_regionName;
  2249. pRegionName->Set((BYTE*)pName, strlen(pName)+1);
  2250. pValues->SetPropertyCString("region", pRegionName);
  2251.     }
  2252.     HX_RELEASE(pRegionName);
  2253.     pLayoutStream->SetProperties(pValues);
  2254.     pValues->Release();
  2255. }
  2256. if(!pRegion->m_bImplicitRegion)
  2257. {
  2258.     addSiteForRenderer(pPlayToAssoc, pSourceInfo, pRenderer, bNoRegion);
  2259. }
  2260.                 // /XXXEH- end of "To do: this is same code as...".
  2261.                 // /^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2262.     }
  2263. }
  2264.         // XXXMEH - now we re-adjust the z-order.
  2265.         if (pZOrderBox)
  2266.         {
  2267.             resolveZOrder(pZOrderBox, m_ulCurrentTime);
  2268.         }
  2269. HX_RELEASE(pLayoutStream);
  2270.     }
  2271.     else    // non-windowed renderer
  2272.     {
  2273. if(pPlayToAssoc)
  2274. {
  2275.     SMILSourceInfo* pSourceInfo = NULL;
  2276.     CHXSimpleList* pRendererList = NULL;
  2277.     if (NULL == pPlayToAssoc->m_sourceMap[uStreamNumber])
  2278.     {
  2279. pPlayToAssoc->m_sourceMap[uStreamNumber] = new CHXSimpleList();
  2280. pPlayToAssoc->m_ulDuration = ulDuration - ulDelay;
  2281. bHandleElement = TRUE;
  2282.     }
  2283.     
  2284.     pSourceInfo = new SMILSourceInfo;
  2285.     pSourceInfo->m_pStream = pStream;
  2286.     if(pSourceInfo->m_pStream)
  2287.     {
  2288. pSourceInfo->m_pStream->AddRef();
  2289.     }
  2290.     pSourceInfo->m_pRenderer = pRenderer;
  2291.     if(pSourceInfo->m_pRenderer)
  2292.     {
  2293. pSourceInfo->m_pRenderer->AddRef();
  2294.     }
  2295.     pSourceInfo->m_pRendererEventHook = NULL;
  2296.     pSourceInfo->m_ulDelay = ulDelay;
  2297.     // /Holy ancient typo, batman!!  This was "p->m = ulDur = ulDelay"
  2298.     // but it meant to say "p->m = ulDur - [not '='!] ulDelay".  Doh!.
  2299.     // Ran across this while fixing PR 79699 and this change is needed
  2300.     // for PR 81715 crash to happen (otherwise 81715 freezes player): 
  2301.     pSourceInfo->m_ulDuration = ulDuration - ulDelay;
  2302.     
  2303.     pRendererList = (CHXSimpleList*) pPlayToAssoc->m_sourceMap[uStreamNumber];
  2304.     pRendererList->AddTail(pSourceInfo);
  2305. }
  2306.     }
  2307.     // We need to set the following parameters into the renderer:
  2308.     //
  2309.     // SMIL default namespace
  2310.     // rn:backgroundOpacity
  2311.     // rn:mediaOpacity
  2312.     // rn:chromaKey
  2313.     // rn:chromaKeyTolerance
  2314.     // rn:chromaKeyOpacity
  2315.     // any <param> children properties
  2316.     //
  2317.     if (pPlayToAssoc)
  2318.     {
  2319.         // QI the renderer for IHXValues
  2320.         IHXValues* pRendValues = NULL;
  2321.         pRenderer->QueryInterface(IID_IHXValues, (void**) &pRendValues);
  2322.         if (pRendValues)
  2323.         {
  2324.             // Set the default namespace
  2325.             if (m_pSMILDefaultNamespaceStr)
  2326.             {
  2327.                 pRendValues->SetPropertyCString("SMILDefaultNamespace",
  2328.                                                 m_pSMILDefaultNamespaceStr);
  2329.             }
  2330.             // Now, if any of the opacity/chromaKey parameters
  2331.             // were specified, then we need to set them into the 
  2332.             // renderer as well.
  2333.             //
  2334.             // First we need to get the source
  2335.             CSmilSource* pSource = getSource(pPlayToAssoc->m_id);
  2336.             if (pSource)
  2337.             {
  2338.                 if (pSource->m_bBackgroundOpacitySpecified)
  2339.                 {
  2340.                     pRendValues->SetPropertyULONG32("backgroundOpacity",
  2341.                                                     pSource->m_ulBackgroundOpacity);
  2342.                 }
  2343.                 if (pSource->m_bMediaOpacitySpecified)
  2344.                 {
  2345.                     pRendValues->SetPropertyULONG32("mediaOpacity",
  2346.                                                     pSource->m_ulMediaOpacity);
  2347.                 }
  2348.                 if (pSource->m_bChromaKeySpecified)
  2349.                 {
  2350.                     pRendValues->SetPropertyULONG32("chromaKey",
  2351.                                                     pSource->m_ulChromaKey);
  2352.                     pRendValues->SetPropertyULONG32("chromaKeyTolerance",
  2353.                                                     pSource->m_ulChromaKeyTolerance);
  2354.                     pRendValues->SetPropertyULONG32("chromaKeyOpacity",
  2355.                                                     pSource->m_ulChromaKeyOpacity);
  2356.                 }
  2357. // /To help fix PR 59951 (SMIL part of the fix), we need to
  2358. // notify the renderer what the region width and height is;
  2359. // that allows the renderer to resize its internal window to
  2360. // fill its region if it has no intrinsic width or height:
  2361. ULONG32 ulDisplayAreaWidth = 0;
  2362. ULONG32 ulDisplayAreaHeight = 0;
  2363. if (pSource->m_region.GetLength()>0  &&  pRegion)
  2364. {
  2365.     ulDisplayAreaWidth =  // /Region size:
  2366.     pRegion->m_rect.right - pRegion->m_rect.left;
  2367.     ulDisplayAreaHeight =  // /Region size:
  2368.     pRegion->m_rect.bottom - pRegion->m_rect.top;
  2369. }
  2370. // /However, if the media element has a "width" attribute
  2371. // set, we should use it instead:
  2372. if (pSource->m_Rect.m_dWidth > 0)
  2373. {
  2374.     ulDisplayAreaWidth = pSource->m_Rect.m_dWidth;
  2375. }
  2376. // /Same for if the media element has a "height" attribute
  2377. // set; we should use it instead:
  2378. if (pSource->m_Rect.m_dHeight > 0)
  2379. {
  2380.     ulDisplayAreaHeight = pSource->m_Rect.m_dHeight;
  2381. }
  2382. // /Now, notify the renderer what size its display area is:
  2383. if (ulDisplayAreaWidth > 0)
  2384. {
  2385.     pRendValues->SetPropertyULONG32("regionWidth",
  2386.     ulDisplayAreaWidth);
  2387. }
  2388. if (ulDisplayAreaHeight > 0)
  2389. {
  2390.     pRendValues->SetPropertyULONG32("regionHeight",
  2391.     ulDisplayAreaHeight);
  2392. }
  2393.                 // Add any param children (if there are any)
  2394.                 // Note that these will be added as CString properties,
  2395.                 // rather than ULONG32 properties as the opacity properties
  2396.                 // Also note that the FALSE arguments below mean that
  2397.                 // we will pass ALL <param> children to the client, regardless
  2398.                 // of whether they have rn:delivery="server" or rn:delivery="client"
  2399.                 if (hasParamChildren(pSource, FALSE))
  2400.                 {
  2401.                     addParamProperties(pSource,
  2402.                                        pRendValues,
  2403.                                        m_pContext,
  2404.                                        FALSE);
  2405.                 }
  2406.             }
  2407.         }
  2408.         HX_RELEASE(pRendValues);
  2409. IHXPersistentRenderer* pPersistentRenderer = NULL;
  2410. if (HXR_OK == pRenderer->QueryInterface(IID_IHXPersistentRenderer, (void**)&pPersistentRenderer))
  2411. {
  2412.     pPlayToAssoc->m_bIsPersistentSource = TRUE;
  2413. }
  2414. HX_RELEASE(pPersistentRenderer);
  2415.     }
  2416.     // Set up listening for external events coming from this
  2417.     // renderer, if there are any
  2418.     if (m_pSmilParser && pPlayToAssoc)
  2419.     {
  2420.         // Are there any external events associated with
  2421.         // this renderer?
  2422.         if (m_pSmilParser->anyExternalEvents(pPlayToAssoc->m_id))
  2423.         {
  2424.             // We do have some external events, so first we
  2425.             // need to set up the SMIL renderer as an event sink,
  2426.             // if it is not already
  2427.             if (!m_bEventSinkWasSetup)
  2428.             {
  2429.                 // TRUE adds us, FALSE removes us
  2430.                 addRemoveEventSink(TRUE);
  2431.             }
  2432.             // Loop through the external events based off
  2433.             // of this renderer, and add filter rules based on
  2434.             // each event.
  2435.             ExternalEventInfo* pInfo =
  2436.                 m_pSmilParser->getFirstExternalEvent(pPlayToAssoc->m_id);
  2437.             while (pInfo)
  2438.             {
  2439.                 // Add a rule for this external event
  2440.                 addEventSinkFilterRule(pPlayToAssoc->m_URL, NULL,
  2441.                                        pInfo->m_PrefixedEventName);
  2442.                 // Get the next external event
  2443.                 pInfo = m_pSmilParser->getNextExternalEvent(pPlayToAssoc->m_id);
  2444.             }
  2445.         }
  2446.     }
  2447.     // update the stream timing if it's been called in handleSourceUpdate()
  2448.     if(m_pDeferredSourceMap)
  2449.     {
  2450. SMILDeferredSourceInfo* pDeferredInfo = NULL;
  2451. const char* pDeferredID = (const char*)pPlayToAssoc->m_id;
  2452. if(m_pDeferredSourceMap->Lookup(pDeferredID,
  2453.     (void*&)pDeferredInfo))
  2454. {
  2455.     CSmilElement* pThisElement = 
  2456. m_pSmilParser->findElement(pDeferredID);
  2457. #if 0     /* Remove: it's causing problems for discrete media updates
  2458.      * like PR 69780 & PR 79748 (which worked OK on 20020618 but
  2459.      * was broken (elsewhere in the code) after that:
  2460.      */
  2461.     if(pThisElement &&
  2462. pThisElement->m_bBeginOffsetSet)
  2463.     {
  2464. if((INT32)pDeferredInfo->m_ulDuration > pThisElement->m_lBeginOffset)
  2465. {
  2466.     updateStreamTiming(pDeferredID, 
  2467. #if 0 /*Remove: it's causing problems for non-neg begin cases like PR 79699: */
  2468. (UINT32)((INT32)pDeferredInfo->m_ulDuration -
  2469. // /Fixes Timing Interop cases, including 1.33,
  2470. // prev_begin_in_a_par6.smil, which was playing 2 sec
  2471. // too long due to -2 sec beginOffset being used here
  2472. (pThisElement->m_lBeginOffset<0?
  2473. 0:pThisElement->m_lBeginOffset) ) );
  2474. #else
  2475. (UINT32)((INT32)pDeferredInfo->m_ulDuration) );
  2476. #endif
  2477. }
  2478. else
  2479. {
  2480.     updateStreamTiming(pDeferredID, 0);
  2481. }
  2482.     }
  2483.     else
  2484. #endif
  2485.     {
  2486. updateStreamTiming(pDeferredID, pDeferredInfo->m_ulDuration);
  2487.     }
  2488. }
  2489.     }
  2490.     if (pPlayToAssoc)
  2491.     {
  2492. const char* pID = (const char*)pPlayToAssoc->m_id;
  2493. {
  2494.     CSmilElement* pThisElement = m_pSmilParser->findElement(pID);
  2495.     if (pThisElement)
  2496.     {
  2497. // /make sure we don't reset the stream's duration or delay
  2498. // if the renderer isn't init'd yet (PR 62688-case2) & others:
  2499. // /DOH!! Somehow, I checked the following without "= TRUE",
  2500. // causing PR 59851 to fail.  Fixes PR 59851 once again:
  2501. pThisElement->m_bRendererInitialized = TRUE;
  2502.     }
  2503. }
  2504.     }
  2505.     // Add this renderer to the media ID -> renderer map
  2506.     if (pPlayToAssoc && pRenderer)
  2507.     {
  2508.         addRendererToMap((const char*) pPlayToAssoc->m_id, pRenderer);
  2509.     }
  2510.     // If this renderer specifies an event handler, OR this renderer IS
  2511.     // an event handler for another renderer, then setup the event pipe
  2512.     if (pPlayToAssoc)
  2513.     {
  2514.         // Get this media's id
  2515.         const char* pszID = (const char*) pPlayToAssoc->m_id;
  2516.         // Look up the element
  2517.         CSmilElement* pEl = m_pSmilParser->findElement(pszID);
  2518.         if (pEl && pEl->m_pNode)
  2519.         {
  2520.             // Cast to a source
  2521.             CSmilSource* pSrc = (CSmilSource*) pEl;
  2522.             // Does this media specify a handler or is
  2523.             // this media a handler?
  2524.             if (pSrc->m_HandlerID.GetLength() > 0)
  2525.             {
  2526.                 // This media specifies a handler
  2527.                 setupEventPipe((const char*) pEl->m_pNode->m_id,
  2528.                                (const char*) pSrc->m_HandlerID,
  2529.                                NULL);
  2530.             }
  2531.             else if (pSrc->m_HandlerFor.GetLength() > 0)
  2532.             {
  2533.                 // This media IS a handler
  2534.                 setupEventPipe((const char*) pSrc->m_HandlerFor,
  2535.                                (const char*) pEl->m_pNode->m_id,
  2536.                                NULL);
  2537.             }
  2538.         }
  2539.     }
  2540.     if (bHandleElement)
  2541.     {
  2542. handleElements();
  2543.     }
  2544.     return HXR_OK;
  2545. }
  2546. #if defined(_UNIX)  &&  (!(defined(_BEOS)))  &&  defined(USE_XWINDOWS)
  2547. XData*  CSmilDocumentRenderer::InitXVisualSupport(IHXSite* pSite, HXxWindow* pWnd)
  2548. {
  2549.     // create new XData object
  2550.     XData* pxData = new XData();
  2551.     // use the pointer to the X display and window
  2552.     // conveniently given us by CHXSiteWindowed::HandleEvent
  2553.     m_pPixmapDisplay = (Display*) pWnd->display;
  2554.     Window window = (Window) pWnd->window; 
  2555.     // save ptr to display in XData object also...
  2556.     pxData->m_Display = m_pPixmapDisplay;
  2557.     // get visual & set m_depth
  2558.     XWindowAttributes attr;
  2559.     XLockDisplay(m_pPixmapDisplay);
  2560.     XGetWindowAttributes(m_pPixmapDisplay, window, &attr);
  2561.     XUnlockDisplay(m_pPixmapDisplay);
  2562.     // get visual info & depth 
  2563.     XVisualInfo visInfoMask;
  2564.     memset(&visInfoMask, 0, sizeof(XVisualInfo));
  2565.     visInfoMask.visualid = attr.visual->visualid;
  2566.     if (m_pVisualInfo)
  2567.     {
  2568. XFree(m_pVisualInfo);
  2569. m_pVisualInfo = NULL;
  2570.     }
  2571.     int nv;
  2572.     XLockDisplay(m_pPixmapDisplay);
  2573.     m_pVisualInfo  = XGetVisualInfo(m_pPixmapDisplay, VisualIDMask, &visInfoMask, &nv);
  2574.     XUnlockDisplay(m_pPixmapDisplay);
  2575.     UINT32 nDepth = 32;
  2576.     nDepth = (UINT32)m_pVisualInfo->depth;
  2577.     pxData->m_colormap = attr.colormap; 
  2578.     // get bits per pixel information for the best depth we can display
  2579.     ULONG32 bitsPerPixel = 32;
  2580.     int i, n;
  2581.     XLockDisplay(m_pPixmapDisplay);
  2582.     XPixmapFormatValues *pixmap_formats = XListPixmapFormats(m_pPixmapDisplay, &n);
  2583.     XUnlockDisplay(m_pPixmapDisplay);
  2584.     if (pixmap_formats) 
  2585.     {
  2586. for (i = 0; i < n; i++)
  2587. {
  2588.     if (pixmap_formats[i].depth == nDepth)
  2589.     {
  2590.         bitsPerPixel = pixmap_formats[i].bits_per_pixel;
  2591.     }
  2592.  }
  2593.     }
  2594.     XFree(pixmap_formats);
  2595.     // get site size
  2596.     HXxSize siteWinSize;
  2597.     pSite->GetSize(siteWinSize);
  2598.     pxData->m_backgroundBitmapInfoHeader.biSize = sizeof(HXBitmapInfoHeader);  
  2599.     pxData->m_backgroundBitmapInfoHeader.biWidth = siteWinSize.cx;
  2600.     pxData->m_backgroundBitmapInfoHeader.biHeight = siteWinSize.cy;
  2601.     pxData->m_backgroundBitmapInfoHeader.biPlanes = 1; // just seems to be the convention  
  2602.     pxData->m_backgroundBitmapInfoHeader.biBitCount = bitsPerPixel;
  2603.     HX_ASSERT(pxData->m_backgroundBitmapInfoHeader.biBitCount % 8 == 0);
  2604.     // BI_RGB just seems to be the convention 
  2605.     switch (pxData->m_backgroundBitmapInfoHeader.biBitCount) 
  2606.     {
  2607. case 8:
  2608. case 24:
  2609. case 32:
  2610.     pxData->m_backgroundBitmapInfoHeader.biCompression = BI_RGB;
  2611.     break;
  2612. case 16:
  2613.     pxData->m_backgroundBitmapInfoHeader.biCompression = HXCOLOR_RGB565_ID;
  2614.     break;
  2615. default:
  2616.     HX_ASSERT(FALSE);
  2617.     }
  2618.     pxData->m_backgroundBitmapInfoHeader.biSizeImage = //size of image (bytes):
  2619. pxData->m_backgroundBitmapInfoHeader.biWidth * pxData->m_backgroundBitmapInfoHeader.biHeight *  
  2620. pxData->m_backgroundBitmapInfoHeader.biBitCount;
  2621.     pxData->m_backgroundBitmapInfoHeader.biXPelsPerMeter = 0;   
  2622.     pxData->m_backgroundBitmapInfoHeader.biYPelsPerMeter = 0;   
  2623.     pxData->m_backgroundBitmapInfoHeader.biClrUsed = 0;  
  2624.     pxData->m_backgroundBitmapInfoHeader.biClrImportant = 0;  
  2625.     pxData->m_backgroundBitmapInfoHeader.rcolor = m_pVisualInfo->red_mask; 
  2626.     pxData->m_backgroundBitmapInfoHeader.gcolor = m_pVisualInfo->green_mask;   
  2627.     pxData->m_backgroundBitmapInfoHeader.bcolor = m_pVisualInfo->blue_mask; 
  2628.     XLockDisplay(m_pPixmapDisplay);
  2629.     pxData->m_Pixmap = XCreatePixmap(m_pPixmapDisplay, 
  2630.      window,
  2631.      pxData->m_backgroundBitmapInfoHeader.biWidth, 
  2632.      pxData->m_backgroundBitmapInfoHeader.biHeight, 
  2633.      nDepth);
  2634.     XUnlockDisplay(m_pPixmapDisplay);
  2635.     return pxData;
  2636. }
  2637. #endif
  2638. #if defined(_DEBUG)
  2639. void CSmilDocumentRenderer::DumpEventQueue()
  2640. {
  2641.     MLOG_EVENT(m_pErrorMessages,
  2642.                "======================================================n"
  2643.                "Event Queue at %lu Current Group %d (%lu events):n"    
  2644.                "            type    time grp ohs ignn",
  2645.                m_ulCurrentTime, m_uCurrentGroupIndex,
  2646.                (m_pEventList? m_pEventList->GetCount() : 0));
  2647.     if (m_pEventList)
  2648.     {
  2649.         LISTPOSITION pos = m_pEventList->GetHeadPosition();
  2650.         while(pos)
  2651.         {
  2652.             CSmilLayoutEvent* pEvent =
  2653.                 (CSmilLayoutEvent*) m_pEventList->GetNext(pos);
  2654.             if (pEvent)
  2655.             {
  2656.                 MLOG_EVENT(m_pErrorMessages,
  2657.                            "%16s %7lu  %1u   %1lu   %1lu",
  2658.                            pEvent->getEventTypeName(),
  2659.                            pEvent->m_ulEventTime,
  2660.                            pEvent->m_uGroupIndex,
  2661.                            pEvent->m_bOnlyHideSite,
  2662.                            pEvent->m_bIgnorEvent);
  2663.                 switch (pEvent->m_type)
  2664.                 {
  2665.                     case CSmilLayoutEvent::eShowSite:
  2666.                     case CSmilLayoutEvent::eHideSite:
  2667.                         {
  2668.                             CSmilShowSiteEvent* pShow = (CSmilShowSiteEvent*) pEvent;
  2669.                             MLOG_EVENT(m_pErrorMessages,
  2670.                                        "tmedia=%stregion=%sn",
  2671.                                        pShow->getMediaID(),
  2672.                                        pShow->getRegionID());
  2673.                         }
  2674.                         break;
  2675.                     default:
  2676.                         MLOG_EVENT(m_pErrorMessages, "n");
  2677.                 }
  2678.             }
  2679.         }
  2680.     }
  2681.     MLOG_EVENT(m_pErrorMessages,
  2682.                "======================================================n");
  2683. }
  2684. void CSmilDocumentRenderer::DumpZOrder(CSmilBasicBox* pBox, UINT32 ulIndentLevel)
  2685. {
  2686.     if (pBox)
  2687.     {
  2688.         for (UINT32 i = 0; i < ulIndentLevel; i++)
  2689.         {
  2690.             MLOG_LAYOUT(m_pErrorMessages, "t");
  2691.         }
  2692.         BOOL        bIsRoot = (pBox->m_pParent == NULL ? TRUE : FALSE);
  2693.         const char* pszName = NULL;
  2694.         if (bIsRoot)
  2695.         {
  2696.             pszName = "root";
  2697.         }
  2698.         else
  2699.         {
  2700.             CSmilBasicRegion* pReg = (CSmilBasicRegion*) pBox;
  2701.             pszName = (const char*) pReg->m_region;
  2702.         }
  2703.         MLOG_LAYOUT(m_pErrorMessages, "site=0x%08xt(%s)tzOrder=%ldn",
  2704.                     pBox->m_pSite, pszName, getSiteZIndex(pBox->m_pSite));
  2705.         // Dump children
  2706.         if (pBox->m_pChildList)
  2707.         {
  2708.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  2709.             while (pos)
  2710.             {
  2711.                 CSmilBasicBox* pChildBox = (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  2712.                 DumpZOrder(pChildBox, ulIndentLevel + 1);
  2713.             }
  2714.         }
  2715.     }
  2716. }
  2717. void CSmilDocumentRenderer::DumpAllGroupInfo(UINT32 ulTime)
  2718. {
  2719.     if (m_pParent)
  2720.     {
  2721.         IHXPlayer* pPlayer = m_pParent->getPlayer();
  2722.         if (pPlayer)
  2723.         {
  2724.            IHXGroupManager* pGroupManager = NULL;
  2725.            pPlayer->QueryInterface(IID_IHXGroupManager, (void**) &pGroupManager);
  2726.            if (pGroupManager)
  2727.            {
  2728.                MLOG_SRC(m_pErrorMessages,"Group Information Dump at %lu:n", ulTime);
  2729.                UINT16 usNumGroups = pGroupManager->GetGroupCount();
  2730.                UINT16 usCurGroup  = 0;
  2731.                pGroupManager->GetCurrentGroup(usCurGroup);
  2732.                MLOG_SRC(m_pErrorMessages,"tNumber of Groups: %un", usNumGroups);
  2733.                MLOG_SRC(m_pErrorMessages,"tCurrent Group:    %un", usCurGroup);
  2734.                for (UINT16 i = 0; i < usNumGroups; i++)
  2735.                {
  2736.                    IHXGroup* pGroup = NULL;
  2737.                    pGroupManager->GetGroup(i, pGroup);
  2738.                    if (pGroup)
  2739.                    {
  2740.                        MLOG_SRC(m_pErrorMessages,"tGroup %u Info:n", i);
  2741.                        UINT16 usNumTracks = pGroup->GetTrackCount();
  2742.                        MLOG_SRC(m_pErrorMessages,"ttNumber of Tracks: %un", usNumTracks);
  2743.                        MLOG_SRC(m_pErrorMessages,"ttGroup Properties:n");
  2744.                        IHXValues* pGrpProp = pGroup->GetGroupProperties();
  2745.                        if (pGrpProp)
  2746.                        {
  2747.                            DumpAllProperties(pGrpProp, 3);
  2748.                        }
  2749.                        HX_RELEASE(pGrpProp);
  2750.                        // Dump track properties
  2751.                        for (UINT16 j = 0; j < usNumTracks; j++)
  2752.                        {
  2753.                            IHXValues* pTrackValues = NULL;
  2754.                            pGroup->GetTrack(j, pTrackValues);
  2755.                            if (pTrackValues)
  2756.                            {
  2757.                                MLOG_SRC(m_pErrorMessages,"ttTrack %u Properties:n", j);
  2758.                                DumpAllProperties(pTrackValues, 3);
  2759.                            }
  2760.                            HX_RELEASE(pTrackValues);
  2761.                        }
  2762.                    }
  2763.                    HX_RELEASE(pGroup);
  2764.                }
  2765.            }
  2766.            HX_RELEASE(pGroupManager);
  2767.         }
  2768.     }
  2769. }
  2770. void CSmilDocumentRenderer::DumpAllProperties(IHXValues* pValues, UINT32 ulNumTabIndent)
  2771. {
  2772.     if (pValues)
  2773.     {
  2774.         // Dump CString properties
  2775. //        char        szDbgStr[256];
  2776.         UINT32      i       = 0;
  2777.         IHXBuffer* pValue  = NULL;
  2778.         const char* pszName = NULL;
  2779.         HX_RESULT   rv      = pValues->GetFirstPropertyCString(pszName, pValue);
  2780.         while (SUCCEEDED(rv))
  2781.         {
  2782. //            for (i = 0; i < ulNumTabIndent; i++) DEBUGPRINTF(szDbgStr, "t");
  2783. //            DEBUGPRINTF(szDbgStr, "%s = %sn", pszName,
  2784. //                        (const char*) pValue->GetBuffer());
  2785.             HX_RELEASE(pValue);
  2786.             rv = pValues->GetNextPropertyCString(pszName, pValue);
  2787.         }
  2788.         // Dump ULONG32 properties
  2789.         UINT32 ulValue = 0;
  2790.         rv = pValues->GetFirstPropertyULONG32(pszName, ulValue);
  2791.         while (SUCCEEDED(rv))
  2792.         {
  2793. //            for (i = 0; i < ulNumTabIndent; i++) DEBUGPRINTF(szDbgStr, "t");
  2794. //            DEBUGPRINTF(szDbgStr, "%s = %lun", pszName, ulValue);
  2795.             HX_RELEASE(pValue);
  2796.             rv = pValues->GetNextPropertyULONG32(pszName, ulValue);
  2797.         }
  2798.         // Dump Buffer properties
  2799.         rv = pValues->GetFirstPropertyBuffer(pszName, pValue);
  2800.         while (SUCCEEDED(rv))
  2801.         {
  2802. //            for (i = 0; i < ulNumTabIndent; i++) DEBUGPRINTF(szDbgStr, "t");
  2803. //            DEBUGPRINTF(szDbgStr, "%s = ", pszName);
  2804.             UINT32 ulSize = pValue->GetSize();
  2805.             BYTE*  pBuf   = pValue->GetBuffer();
  2806.             for (i = 0; i < ulSize; i++)
  2807.             {
  2808. //                DEBUGPRINTF(szDbgStr, "%02X ", pBuf[i]);
  2809.             }
  2810. //            DEBUGPRINTF(szDbgStr, "n");
  2811.             HX_RELEASE(pValue);
  2812.             rv = pValues->GetNextPropertyBuffer(pszName, pValue);
  2813.         }
  2814.     }
  2815. }
  2816. void CSmilDocumentRenderer::DumpAllSiteInfo(const char* pszFileName, UINT32 ulTime)
  2817. {
  2818.     if (pszFileName)
  2819.     {
  2820.         FILE* fp = fopen(pszFileName, "a");
  2821.         if (fp)
  2822.         {
  2823.             fprintf(fp, "======================================================n");
  2824.             fprintf(fp, "Dumping all site info at time %lu:nn", ulTime);
  2825.             DumpBoxSiteInfo(m_pRootLayout, fp, 0);
  2826.             fprintf(fp, "======================================================n");
  2827.             fclose(fp);
  2828.         }
  2829.     }
  2830. }
  2831. void CSmilDocumentRenderer::DumpBoxSiteInfo(CSmilBasicBox* pBox, FILE* fp, UINT32 ulIndentLevel)
  2832. {
  2833.     if (pBox && fp && ulIndentLevel < 64)
  2834.     {
  2835.         // Set up indent string
  2836.         char szIndent[64]; /* Flawfinder: ignore */
  2837.         for (UINT32 i = 0; i < ulIndentLevel; i++) szIndent[0] = 't';
  2838.         szIndent[ulIndentLevel] = '';
  2839.         // Dump info on this box itself
  2840.         //
  2841.         // Is this box a root?
  2842.         if (pBox->m_pParent)
  2843.         {
  2844.             // It has a parent, so it can't be a root - 
  2845.             // it must be a region
  2846.             CSmilBasicRegion* pRegion = (CSmilBasicRegion*) pBox;
  2847.             fprintf(fp, "%sDumping site info for region %s:n",
  2848.                     szIndent, (const char*) pRegion->m_region);
  2849.         }
  2850.         else
  2851.         {
  2852.             // No parent, so it is a root
  2853.             fprintf(fp, "%sDumping site info for root box:n", szIndent);
  2854.         }
  2855.         // Dump the info on this box's site
  2856.         HXxSize  cSize = {0, 0};
  2857.         HXxPoint cPos  = {0, 0};
  2858.         if (pBox->m_pSite)
  2859.         {
  2860.             pBox->m_pSite->GetSize(cSize);
  2861.             pBox->m_pSite->GetPosition(cPos);
  2862.         }
  2863.         fprintf(fp, "%stsize=(%ld,%ld) pos=(%ld,%ld) vis=%lu z-index=%ldn",
  2864.                 szIndent, cSize.cx, cSize.cy, cPos.x, cPos.y,
  2865.                 isSiteVisible(pBox->m_pSite), getSiteZIndex(pBox->m_pSite));
  2866.         // Dump info on this box's renderer sites
  2867.         if (pBox->m_pChildRendererSiteList)
  2868.         {
  2869.             fprintf(fp, "%strenderer children sites:n", szIndent);
  2870.             LISTPOSITION pos = pBox->m_pChildRendererSiteList->GetHeadPosition();
  2871.             while (pos)
  2872.             {
  2873.                 IHXSite* pChildRendSite =
  2874.                     (IHXSite*) pBox->m_pChildRendererSiteList->GetNext(pos);
  2875.                 if (pChildRendSite)
  2876.                 {
  2877.                     pChildRendSite->GetSize(cSize);
  2878.                     pChildRendSite->GetPosition(cPos);
  2879.                     CHXString cMediaID("unknown");
  2880.                     getMediaIDFromSite(pChildRendSite, cMediaID);
  2881.                     fprintf(fp, "%sttid=%s size=(%ld,%ld) pos=(%ld,%ld) vis=%lu z-index=%ldn",
  2882.                             szIndent, (const char*) cMediaID,
  2883.                             cSize.cx, cSize.cy, cPos.x, cPos.y,
  2884.                             isSiteVisible(pChildRendSite),
  2885.                             getSiteZIndex(pChildRendSite));
  2886.                 }
  2887.             }
  2888.         }
  2889.         // Now recursively force updates on any children
  2890.         if (pBox->m_pChildList)
  2891.         {
  2892.             fprintf(fp, "%stbox children:n", szIndent);
  2893.             LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  2894.             while (pos)
  2895.             {
  2896.                 CSmilBasicBox* pChildBox =
  2897.                     (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  2898.                 DumpBoxSiteInfo(pChildBox, fp, ulIndentLevel + 1);
  2899.             }
  2900.         }
  2901.     }
  2902. }
  2903. #endif // #if defined(_DEBUG)
  2904. HX_RESULT CSmilDocumentRenderer::getMediaIDFromSite(IHXSite*      pSite,
  2905.                                                     REF(CHXString) rcStr)
  2906. {
  2907.     HX_RESULT retVal = HXR_FAIL;
  2908.     if (pSite && m_pSiteWatcherMap)
  2909.     {
  2910.         void* pVoid = NULL;
  2911.         if (m_pSiteWatcherMap->Lookup(pSite, pVoid) && pVoid)
  2912.         {
  2913.             CSmilSiteWatcher* pWatcher = (CSmilSiteWatcher*) pVoid;
  2914.             retVal = HXR_OK;
  2915.             rcStr = pWatcher->GetSourceID();
  2916.         }
  2917.     }
  2918.     return retVal;
  2919. }
  2920. void CSmilDocumentRenderer::queueSiteForAnimationRedraw(IHXSite* pSite)
  2921. {
  2922.     if (pSite && m_pAnimSiteRedrawMap)
  2923.     {
  2924.         m_pAnimSiteRedrawMap->SetAt((void*) pSite, (void*) pSite);