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

Symbian

开发平台:

Visual C++

  1. // we used to seek to 0 (the returned value), but now we
  2. // just don't do a seek:
  3. // (Note: this problem was found while fixing PR 22655.)
  4. if(bFragFoundAndResolved)
  5. {
  6.     pPlayer->Seek(ulFragmentOffset);
  7.     pPlayer->Begin();
  8. }
  9.     }
  10.     pMgr->Release();
  11. }
  12.     }
  13.     else
  14.     {
  15. rc = HXR_FAIL;
  16.     }
  17.     return rc;
  18. }
  19. void
  20. CSmilDocumentRenderer::resizeRegion(const char* pRegionName,
  21.     HXxSize* pNewSize)
  22. {
  23.     CSmilBasicRegion* pRegion = getRegionByID(pRegionName);
  24.     if(pRegion)
  25.     {
  26. pRegion->m_rect.right = pRegion->m_rect.left + pNewSize->cx;
  27. pRegion->m_rect.bottom = pRegion->m_rect.top + pNewSize->cy;
  28.     }
  29. }
  30. void
  31. CSmilDocumentRenderer::repositionRegion(const char* pRegionName,
  32.       HXxPoint* pNewPosition)
  33. {
  34.     CSmilBasicRegion* pRegion = getRegionByID(pRegionName);
  35.     if(pRegion)
  36.     {
  37. HXxSize size;
  38. size.cx = HXxRECT_WIDTH(pRegion->m_rect);
  39. size.cy = HXxRECT_HEIGHT(pRegion->m_rect);
  40. pRegion->m_rect.left = pNewPosition->x;
  41. pRegion->m_rect.top = pNewPosition->y;
  42. pRegion->m_rect.right = pRegion->m_rect.left + size.cx;
  43. pRegion->m_rect.bottom = pRegion->m_rect.top + size.cy;
  44.     }
  45. }
  46. void CSmilDocumentRenderer::setMediaNativeSize(const char* pszID, HXxSize cSize)
  47. {
  48.     if (pszID &&
  49.         cSize.cx > 0 && cSize.cy > 0)
  50.     {
  51.         if (!m_bLayoutElementPresent ||
  52.             (m_bLayoutElementPresent && m_bEmptyLayout))
  53.         {
  54.             // Get the source for this renderer. Make sure
  55.             // this source is not trying to manipulate the 
  56.             // subregion width and height
  57.             CSmilSource* pSource = getSource(pszID);
  58.             if (pSource &&
  59.                 pSource->m_Rect.m_eWidthType  == CSS2TypeAuto &&
  60.                 pSource->m_Rect.m_eHeightType == CSS2TypeAuto)
  61.             {
  62.                 // Set the width and height of the subregion
  63.                 // to be the media width and height
  64.                 pSource->m_Rect.m_eWidthType  = CSS2TypeLength;
  65.                 pSource->m_Rect.m_dWidth      = (double) cSize.cx;
  66.                 pSource->m_Rect.m_eHeightType = CSS2TypeLength;
  67.                 pSource->m_Rect.m_dHeight     = (double) cSize.cy;
  68.                 // If we have not set the "top" attribute, then
  69.                 // we will explicitly set it here.
  70.                 if (pSource->m_Rect.m_eTopType == CSS2TypeAuto)
  71.                 {
  72.                     // Get the group index for this media
  73.                     UINT16           usGroup = 0;
  74.                     SMILPlayToAssoc* pThisPT = getPlayToAssocByMedia(pszID);
  75.                     if (pThisPT)
  76.                     {
  77.                         usGroup = pThisPT->m_uGroupIndex;
  78.                     }
  79.                     // Find the maximum x and y for all media in this
  80.                     // group playing to the default region
  81.                     double dMaxX = 0.0;
  82.                     double dMaxY = 0.0;
  83.                     if (m_pPlayToAssocList)
  84.                     {
  85.                         LISTPOSITION pos = m_pPlayToAssocList->GetHeadPosition();
  86.                         while (pos)
  87.                         {
  88.                             SMILPlayToAssoc* pPT = (SMILPlayToAssoc*) m_pPlayToAssocList->GetNext(pos);
  89.                             if (pPT &&
  90.                                 pPT->m_id != pszID &&
  91.                                 pPT->m_uGroupIndex == usGroup &&
  92.                                 pPT->m_playTo == "jgje4u5kd845prhd94")
  93.                             {
  94.                                 // This media is playing to the default region 
  95.                                 // and is not the current media. Get the source for
  96.                                 // this media
  97.                                 CSmilSource* pSrc = getSource(pPT->m_id);
  98.                                 if (pSrc)
  99.                                 {
  100.                                     if (pSrc->m_Rect.m_eTopType    == CSS2TypeLength &&
  101.                                         pSrc->m_Rect.m_eHeightType == CSS2TypeLength)
  102.                                     {
  103.                                         double dY = pSrc->m_Rect.m_dTop +
  104.                                                     pSrc->m_Rect.m_dHeight;
  105.                                         if (dY > dMaxY)
  106.                                         {
  107.                                             dMaxY = dY;
  108.                                         }
  109.                                     }
  110.                                     if (pSrc->m_Rect.m_eLeftType  == CSS2TypeLength &&
  111.                                         pSrc->m_Rect.m_eWidthType == CSS2TypeLength)
  112.                                     {
  113.                                         double dX = pSrc->m_Rect.m_dLeft +
  114.                                                     pSrc->m_Rect.m_dWidth;
  115.                                         if (dX > dMaxX)
  116.                                         {
  117.                                             dMaxX = dX;
  118.                                         }
  119.                                     }
  120.                                 }
  121.                             }
  122.                         }
  123.                     }
  124.                     // Set the subregion left of this media
  125.                     pSource->m_Rect.m_eLeftType = CSS2TypeLength;
  126.                     pSource->m_Rect.m_dLeft     = 0.0;
  127.                     // Set the subregion top of this media. If we have
  128.                     // an empty layout, then we put everything at the top
  129.                     // left. If we have NO layout, then we stack the
  130.                     // media up.
  131.                     pSource->m_Rect.m_eTopType = CSS2TypeLength;
  132.                     pSource->m_Rect.m_dTop     = (m_bEmptyLayout ? 0.0 : dMaxY);
  133.                     // We need to update the site watcher's copy
  134.                     // of the subregion rect. So first we have to get
  135.                     // the site watcher
  136.                     CSmilSiteWatcher* pWatcher = getRendererSiteWatcher(pszID);
  137.                     if (pWatcher)
  138.                     {
  139.                         // Now update the site watcher's subregion rect
  140.                         pWatcher->SetSubRegionRect(pSource->m_Rect);
  141.                     }
  142.                     // Update the x max to include this media
  143.                     double dX = pSource->m_Rect.m_dLeft + pSource->m_Rect.m_dWidth;
  144.                     if (dX > dMaxX)
  145.                     {
  146.                         dMaxX = dX;
  147.                     }
  148.                     // Update the y max to include this media
  149.                     double dY = pSource->m_Rect.m_dTop + pSource->m_Rect.m_dHeight;
  150.                     if (dY > dMaxY)
  151.                     {
  152.                         dMaxY = dY;
  153.                     }
  154.                     // Now may need to update the width and height of the root-layout
  155.                     INT32   lMaxX     = (INT32) (dMaxX + 0.5);
  156.                     INT32   lMaxY     = (INT32) (dMaxY + 0.5);
  157.                     HXxSize cRootSize = {lMaxX, lMaxY};
  158.                     if (m_pRootLayout &&
  159.                         m_pRootLayout->m_pSite &&
  160.                         (lMaxX != HXxRECT_WIDTH(m_pRootLayout->m_Rect) ||
  161.                          lMaxY != HXxRECT_HEIGHT(m_pRootLayout->m_Rect)))
  162.                     {
  163.                         m_bDoNotZoom = TRUE;
  164.                         m_pRootLayout->m_pSite->SetSize(cRootSize);
  165.                         m_bDoNotZoom = FALSE;
  166.                         // In the root-layout SetSize() above, we are 
  167.                         // adjusting the size of the root-layout to account
  168.                         // for the additional media which has no layout specified.
  169.                         // We make sure above to disable zooming, since this 
  170.                         // SetSize() doesn't come from resizing the player but
  171.                         // rather from our direct manipulation. Here, we also
  172.                         // need to reset the root-layout's "original size" so
  173.                         // that when we do actually zoom (by resizing the
  174.                         // player) that we know the correct original size
  175.                         m_pRootLayout->m_OriginalSize = cRootSize;
  176.                     }
  177.                 }
  178.             }
  179.         }
  180.     }
  181. }
  182. void CSmilDocumentRenderer::computeRegPoint(HXxRect       cRegionRect,
  183.                                             RegPoint      cRegPointInfo,
  184.                                             REF(HXxPoint) rcRegPoint)
  185. {
  186.     // Compute regPoint.x
  187.     if (cRegPointInfo.m_eLeftType  == CSS2TypeAuto &&
  188.         cRegPointInfo.m_eRightType == CSS2TypeAuto)
  189.     {
  190.         // Both are auto - we'll default to the regionRect left
  191.         rcRegPoint.x = cRegionRect.left;
  192.     }
  193.     else if (cRegPointInfo.m_eLeftType  != CSS2TypeAuto)
  194.     {
  195.         // Take left
  196.         INT32 lLeft = 0;
  197.         if (cRegPointInfo.m_eLeftType == CSS2TypePercentage)
  198.         {
  199.             lLeft = (INT32) (cRegPointInfo.m_dLeft * HXxRECT_WIDTH(cRegionRect) / 100.0 + 0.5);
  200.         }
  201.         else
  202.         {
  203.             lLeft = (INT32) (cRegPointInfo.m_dLeft + 0.5);
  204.         }
  205.         rcRegPoint.x = cRegionRect.left + lLeft;
  206.     }
  207.     else if (cRegPointInfo.m_eLeftType  == CSS2TypeAuto &&
  208.              cRegPointInfo.m_eRightType != CSS2TypeAuto)
  209.     {
  210.         // Take right
  211.         INT32 lRight = 0;
  212.         if (cRegPointInfo.m_eRightType == CSS2TypePercentage)
  213.         {
  214.             lRight = (INT32) (cRegPointInfo.m_dRight * HXxRECT_WIDTH(cRegionRect) / 100.0 + 0.5);
  215.         }
  216.         else
  217.         {
  218.             lRight = (INT32) (cRegPointInfo.m_dRight + 0.5);
  219.         }
  220.         rcRegPoint.x  = cRegionRect.right - lRight;
  221.     }
  222.     // Compute regPoint.y
  223.     if (cRegPointInfo.m_eTopType    == CSS2TypeAuto &&
  224.         cRegPointInfo.m_eBottomType == CSS2TypeAuto)
  225.     {
  226.         // Both are auto - we'll default to the regionRect top
  227.         rcRegPoint.y = cRegionRect.top;
  228.     }
  229.     else if (cRegPointInfo.m_eTopType  != CSS2TypeAuto)
  230.     {
  231.         // Take top
  232.         INT32 lTop = 0;
  233.         if (cRegPointInfo.m_eTopType == CSS2TypePercentage)
  234.         {
  235.             lTop  = (INT32) (cRegPointInfo.m_dTop * HXxRECT_HEIGHT(cRegionRect) / 100.0 + 0.5);
  236.         }
  237.         else
  238.         {
  239.             lTop  = (INT32) (cRegPointInfo.m_dTop + 0.5);
  240.         }
  241.         rcRegPoint.y = cRegionRect.top + lTop;
  242.     }
  243.     else if (cRegPointInfo.m_eTopType    == CSS2TypeAuto &&
  244.              cRegPointInfo.m_eBottomType != CSS2TypeAuto)
  245.     {
  246.         // Take bottom
  247.         INT32 lBottom = 0;
  248.         if (cRegPointInfo.m_eBottomType == CSS2TypePercentage)
  249.         {
  250.             lBottom = (INT32) (cRegPointInfo.m_dBottom * HXxRECT_HEIGHT(cRegionRect) / 100.0 + 0.5);
  251.         }
  252.         else
  253.         {
  254.             lBottom = (INT32) (cRegPointInfo.m_dBottom + 0.5);
  255.         }
  256.         rcRegPoint.y = cRegionRect.bottom - lBottom;
  257.     }
  258. }
  259. HX_RESULT CSmilDocumentRenderer::computeMediaLayout(HXxRect      cRegionRect,
  260.                                                     Fit          eFit,
  261.                                                     HXxPoint     cRegPoint,
  262.                                                     RegAlign     eRegAlign,
  263.                                                     HXxSize      cMediaSize,
  264.                                                     REF(HXxRect) rcMediaRect,
  265.                                                     BOOL         bMediaIsBrush)
  266. {
  267.     HX_RESULT retVal = HXR_OK;
  268.     if (cRegionRect.right  > cRegionRect.left &&
  269.         cRegionRect.bottom > cRegionRect.top  &&
  270.         cMediaSize.cx > 0 && cMediaSize.cy > 0)
  271.     {
  272.         // If the media is a brush, then we always have 
  273.         // fit="fill" behavior
  274.         if (bMediaIsBrush)
  275.         {
  276.             eFit = FitFill;
  277.         }
  278.         // Switch based on fit
  279.         switch (eFit)
  280.         {
  281.             case FitFill:
  282.                 {
  283.                     switch (eRegAlign)
  284.                     {
  285.                         case RegAlignTopLeft:
  286.                             {
  287.                                 rcMediaRect.left   = cRegPoint.x;
  288.                                 rcMediaRect.top    = cRegPoint.y;
  289.                                 rcMediaRect.right  = cRegionRect.right;
  290.                                 rcMediaRect.bottom = cRegionRect.bottom;
  291.                             }
  292.                             break;
  293.                         case RegAlignTopMid:
  294.                             {
  295.                                 rcMediaRect.top    = cRegPoint.y;
  296.                                 rcMediaRect.bottom = cRegionRect.bottom;
  297.                                 computeFillHiddenScaling(eFit, cRegPoint.x,      cMediaSize.cx,
  298.                                                          cRegionRect.left, cRegionRect.right,
  299.                                                          rcMediaRect.left, rcMediaRect.right);
  300.                             }
  301.                             break;
  302.                         case RegAlignTopRight:
  303.                             {
  304.                                 rcMediaRect.left   = cRegionRect.left;
  305.                                 rcMediaRect.top    = cRegPoint.y;
  306.                                 rcMediaRect.right  = cRegPoint.x;
  307.                                 rcMediaRect.bottom = cRegionRect.bottom;
  308.                             }
  309.                             break;
  310.                         case RegAlignMidLeft:
  311.                             {
  312.                                 rcMediaRect.left   = cRegPoint.x;
  313.                                 rcMediaRect.right  = cRegionRect.right;
  314.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  315.                                                          cRegionRect.top, cRegionRect.bottom,
  316.                                                          rcMediaRect.top, rcMediaRect.bottom);
  317.                             }
  318.                             break;
  319.                         case RegAlignCenter:
  320.                             {
  321.                                 computeFillHiddenScaling(eFit, cRegPoint.x, cMediaSize.cx,
  322.                                                          cRegionRect.left, cRegionRect.right,
  323.                                                          rcMediaRect.left, rcMediaRect.right);
  324.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  325.                                                          cRegionRect.top, cRegionRect.bottom,
  326.                                                          rcMediaRect.top, rcMediaRect.bottom);
  327.                             }
  328.                             break;
  329.                         case RegAlignMidRight:
  330.                             {
  331.                                 rcMediaRect.left  = cRegionRect.left;
  332.                                 rcMediaRect.right = cRegPoint.x;
  333.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  334.                                                          cRegionRect.top, cRegionRect.bottom,
  335.                                                          rcMediaRect.top, rcMediaRect.bottom);
  336.                             }
  337.                             break;
  338.                         case RegAlignBottomLeft:
  339.                             {
  340.                                 rcMediaRect.left   = cRegPoint.x;
  341.                                 rcMediaRect.top    = cRegionRect.top;
  342.                                 rcMediaRect.right  = cRegionRect.right;
  343.                                 rcMediaRect.bottom = cRegPoint.y;
  344.                             }
  345.                             break;
  346.                         case RegAlignBottomMid:
  347.                             {
  348.                                 rcMediaRect.top    = cRegionRect.top;
  349.                                 rcMediaRect.bottom = cRegPoint.y;
  350.                                 computeFillHiddenScaling(eFit, cRegPoint.x,  cMediaSize.cx,
  351.                                                          cRegionRect.left, cRegionRect.right,
  352.                                                          rcMediaRect.left, rcMediaRect.right);
  353.                             }
  354.                             break;
  355.                         case RegAlignBottomRight:
  356.                             {
  357.                                 rcMediaRect.left   = cRegionRect.left;
  358.                                 rcMediaRect.right  = cRegPoint.x;
  359.                                 rcMediaRect.top    = cRegionRect.top;
  360.                                 rcMediaRect.bottom = cRegPoint.y;
  361.                             }
  362.                             break;
  363.                     }
  364.                 }
  365.                 break;
  366.             case FitScroll:
  367.             case FitHidden:
  368.                 {
  369.                     switch (eRegAlign)
  370.                     {
  371.                         case RegAlignTopLeft:
  372.                             {
  373.                                 rcMediaRect.left   = cRegPoint.x;
  374.                                 rcMediaRect.top    = cRegPoint.y;
  375.                                 rcMediaRect.right  = cRegPoint.x + cMediaSize.cx;
  376.                                 rcMediaRect.bottom = cRegPoint.y + cMediaSize.cy;
  377.                             }
  378.                             break;
  379.                         case RegAlignTopMid:
  380.                             {
  381.                                 rcMediaRect.top    = cRegPoint.y;
  382.                                 rcMediaRect.bottom = cRegPoint.y + cMediaSize.cy;
  383.                                 computeFillHiddenScaling(eFit, cRegPoint.x, cMediaSize.cx,
  384.                                                          cRegionRect.left, cRegionRect.right,
  385.                                                          rcMediaRect.left, rcMediaRect.right);
  386.                             }
  387.                             break;
  388.                         case RegAlignTopRight:
  389.                             {
  390.                                 rcMediaRect.left   = cRegPoint.x - cMediaSize.cx;
  391.                                 rcMediaRect.top    = cRegPoint.y;
  392.                                 rcMediaRect.right  = cRegPoint.x;
  393.                                 rcMediaRect.bottom = cRegPoint.y + cMediaSize.cy;
  394.                             }
  395.                             break;
  396.                         case RegAlignMidLeft:
  397.                             {
  398.                                 rcMediaRect.left  = cRegPoint.x;
  399.                                 rcMediaRect.right = cRegPoint.x + cMediaSize.cx;
  400.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  401.                                                          cRegionRect.top, cRegionRect.bottom,
  402.                                                          rcMediaRect.top, rcMediaRect.bottom);
  403.                             }
  404.                             break;
  405.                         case RegAlignCenter:
  406.                             {
  407.                                 computeFillHiddenScaling(eFit, cRegPoint.x, cMediaSize.cx,
  408.                                                          cRegionRect.left, cRegionRect.right,
  409.                                                          rcMediaRect.left, rcMediaRect.right);
  410.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  411.                                                          cRegionRect.top, cRegionRect.bottom,
  412.                                                          rcMediaRect.top, rcMediaRect.bottom);
  413.                             }
  414.                             break;
  415.                         case RegAlignMidRight:
  416.                             {
  417.                                 rcMediaRect.left  = cRegPoint.x - cMediaSize.cx;
  418.                                 rcMediaRect.right = cRegPoint.x;
  419.                                 computeFillHiddenScaling(eFit, cRegPoint.y, cMediaSize.cy,
  420.                                                          cRegionRect.top, cRegionRect.bottom,
  421.                                                          rcMediaRect.top, rcMediaRect.bottom);
  422.                             }
  423.                             break;
  424.                         case RegAlignBottomLeft:
  425.                             {
  426.                                 rcMediaRect.left   = cRegPoint.x;
  427.                                 rcMediaRect.top    = cRegPoint.y - cMediaSize.cy;
  428.                                 rcMediaRect.right  = cRegPoint.x + cMediaSize.cx;
  429.                                 rcMediaRect.bottom = cRegPoint.y;
  430.                             }
  431.                             break;
  432.                         case RegAlignBottomMid:
  433.                             {
  434.                                 rcMediaRect.top    = cRegPoint.y - cMediaSize.cy;
  435.                                 rcMediaRect.bottom = cRegPoint.y;
  436.                                 computeFillHiddenScaling(eFit, cRegPoint.x, cMediaSize.cx,
  437.                                                          cRegionRect.left, cRegionRect.right,
  438.                                                          rcMediaRect.left, rcMediaRect.right);
  439.                             }
  440.                             break;
  441.                         case RegAlignBottomRight:
  442.                             {
  443.                                 rcMediaRect.left   = cRegPoint.x - cMediaSize.cx;
  444.                                 rcMediaRect.top    = cRegPoint.y - cMediaSize.cy;
  445.                                 rcMediaRect.right  = cRegPoint.x;
  446.                                 rcMediaRect.bottom = cRegPoint.y;
  447.                             }
  448.                             break;
  449.                     }
  450.                 }
  451.                 break;
  452.             case FitMeet:
  453.             case FitSlice:
  454.                 {
  455.                     INT32 d       = 0; // dummy variable
  456.                     BOOL  bIsMeet = (eFit == FitMeet ? TRUE : FALSE);
  457.                     switch (eRegAlign)
  458.                     {
  459.                         case RegAlignTopLeft:
  460.                             {
  461.                                 // left and top are fixed
  462.                                 rcMediaRect.left = cRegPoint.x;
  463.                                 rcMediaRect.top  = cRegPoint.y;
  464.                                 // compute the rest of the media rect
  465.                                 computeMeetSliceScaling(bIsMeet, 2,
  466.                                                         cRegPoint.x,
  467.                                                         cRegPoint.x + cMediaSize.cx,
  468.                                                         cRegionRect.right,
  469.                                                         cRegPoint.y,
  470.                                                         cRegPoint.y + cMediaSize.cy,
  471.                                                         cRegionRect.bottom,
  472.                                                         0, 0, 0, 0, 0, 0,
  473.                                                         rcMediaRect.right,
  474.                                                         rcMediaRect.bottom,
  475.                                                         d, d);
  476.                             }
  477.                             break;
  478.                         case RegAlignTopMid:
  479.                             {
  480.                                 // top is fixed
  481.                                 rcMediaRect.top = cRegPoint.y;
  482.                                 // Compute the left and right of the original media
  483.                                 INT32 lMediaLeft  = 0;
  484.                                 INT32 lMediaRight = 0;
  485.                                 computeHalfBounds(cRegPoint.x, cMediaSize.cx,
  486.                                                   lMediaLeft,  lMediaRight);
  487.                                 // Compute the rest of the media rect
  488.                                 computeMeetSliceScaling(bIsMeet, 3,
  489.                                                         cRegPoint.x,
  490.                                                         lMediaLeft,
  491.                                                         cRegionRect.left,
  492.                                                         cRegPoint.x,
  493.                                                         lMediaRight,
  494.                                                         cRegionRect.right,
  495.                                                         cRegPoint.y,
  496.                                                         cRegPoint.y + cMediaSize.cy,
  497.                                                         cRegionRect.bottom,
  498.                                                         0, 0, 0,
  499.                                                         rcMediaRect.left,
  500.                                                         rcMediaRect.right,
  501.                                                         rcMediaRect.bottom,
  502.                                                         d);
  503.                             }
  504.                             break;
  505.                         case RegAlignTopRight:
  506.                             {
  507.                                 // right and top are fixed
  508.                                 rcMediaRect.top   = cRegPoint.y;
  509.                                 rcMediaRect.right = cRegPoint.x;
  510.                                 // compute the rest of the media rect
  511.                                 computeMeetSliceScaling(bIsMeet, 2,
  512.                                                         cRegPoint.x,
  513.                                                         cRegPoint.x - cMediaSize.cx,
  514.                                                         cRegionRect.left,
  515.                                                         cRegPoint.y,
  516.                                                         cRegPoint.y + cMediaSize.cy,
  517.                                                         cRegionRect.bottom,
  518.                                                         0, 0, 0, 0, 0, 0,
  519.                                                         rcMediaRect.left,
  520.                                                         rcMediaRect.bottom,
  521.                                                         d, d);
  522.                             }
  523.                             break;
  524.                         case RegAlignMidLeft:
  525.                             {
  526.                                 // left is fixed
  527.                                 rcMediaRect.left = cRegPoint.x;
  528.                                 // Compute the top and bottom of the original media
  529.                                 INT32 lMediaTop    = 0;
  530.                                 INT32 lMediaBottom = 0;
  531.                                 computeHalfBounds(cRegPoint.y, cMediaSize.cy,
  532.                                                   lMediaTop,  lMediaBottom);
  533.                                 // compute the rest of the media rect
  534.                                 computeMeetSliceScaling(bIsMeet, 3,
  535.                                                         cRegPoint.y,
  536.                                                         lMediaTop,
  537.                                                         cRegionRect.top,
  538.                                                         cRegPoint.x,
  539.                                                         cRegPoint.x + cMediaSize.cx,
  540.                                                         cRegionRect.right,
  541.                                                         cRegPoint.y,
  542.                                                         lMediaBottom,
  543.                                                         cRegionRect.bottom,
  544.                                                         0, 0, 0,
  545.                                                         rcMediaRect.top,
  546.                                                         rcMediaRect.right,
  547.                                                         rcMediaRect.bottom,
  548.                                                         d);
  549.                             }
  550.                             break;
  551.                         case RegAlignCenter:
  552.                             {
  553.                                 // Compute the left and right of the original media
  554.                                 INT32 lMediaLeft  = 0;
  555.                                 INT32 lMediaRight = 0;
  556.                                 computeHalfBounds(cRegPoint.x, cMediaSize.cx,
  557.                                                   lMediaLeft,  lMediaRight);
  558.                                 // Compute the top and bottom of the original media
  559.                                 INT32 lMediaTop    = 0;
  560.                                 INT32 lMediaBottom = 0;
  561.                                 computeHalfBounds(cRegPoint.y, cMediaSize.cy,
  562.                                                   lMediaTop,  lMediaBottom);
  563.                                 // Compute the media rect
  564.                                 computeMeetSliceScaling(bIsMeet, 4,
  565.                                                         cRegPoint.x,
  566.                                                         lMediaLeft,
  567.                                                         cRegionRect.left,
  568.                                                         cRegPoint.y,
  569.                                                         lMediaTop,
  570.                                                         cRegionRect.top,
  571.                                                         cRegPoint.x,
  572.                                                         lMediaRight,
  573.                                                         cRegionRect.right,
  574.                                                         cRegPoint.y,
  575.                                                         lMediaBottom,
  576.                                                         cRegionRect.bottom,
  577.                                                         rcMediaRect.left,
  578.                                                         rcMediaRect.top,
  579.                                                         rcMediaRect.right,
  580.                                                         rcMediaRect.bottom);
  581.                             }
  582.                             break;
  583.                         case RegAlignMidRight:
  584.                             {
  585.                                 // right is fixed
  586.                                 rcMediaRect.right = cRegPoint.x;
  587.                                 // Compute the top and bottom of the original media
  588.                                 INT32 lMediaTop    = 0;
  589.                                 INT32 lMediaBottom = 0;
  590.                                 computeHalfBounds(cRegPoint.y, cMediaSize.cy,
  591.                                                   lMediaTop,  lMediaBottom);
  592.                                 // Compute the rest of the media rect
  593.                                 computeMeetSliceScaling(bIsMeet, 3,
  594.                                                         cRegPoint.x,
  595.                                                         cRegPoint.x - cMediaSize.cx,
  596.                                                         cRegionRect.left,
  597.                                                         cRegPoint.y,
  598.                                                         lMediaTop,
  599.                                                         cRegionRect.top,
  600.                                                         cRegPoint.y,
  601.                                                         lMediaBottom,
  602.                                                         cRegionRect.bottom,
  603.                                                         0, 0, 0,
  604.                                                         rcMediaRect.left,
  605.                                                         rcMediaRect.top,
  606.                                                         rcMediaRect.bottom,
  607.                                                         d);
  608.                             }
  609.                             break;
  610.                         case RegAlignBottomLeft:
  611.                             {
  612.                                 // left and bottom are fixed
  613.                                 rcMediaRect.left   = cRegPoint.x;
  614.                                 rcMediaRect.bottom = cRegPoint.y;
  615.                                 // Compute the rest of the media rect
  616.                                 computeMeetSliceScaling(bIsMeet, 2,
  617.                                                         cRegPoint.y,
  618.                                                         cRegPoint.y - cMediaSize.cy,
  619.                                                         cRegionRect.top,
  620.                                                         cRegPoint.x,
  621.                                                         cRegPoint.x + cMediaSize.cx,
  622.                                                         cRegionRect.right,
  623.                                                         0, 0, 0, 0, 0, 0,
  624.                                                         rcMediaRect.top,
  625.                                                         rcMediaRect.right,
  626.                                                         d, d);
  627.                             }
  628.                             break;
  629.                         case RegAlignBottomMid:
  630.                             {
  631.                                 // bottom is fixed
  632.                                 rcMediaRect.bottom = cRegPoint.y;
  633.                                 // Compute the left and right of the original media
  634.                                 INT32 lMediaLeft  = 0;
  635.                                 INT32 lMediaRight = 0;
  636.                                 computeHalfBounds(cRegPoint.x, cMediaSize.cx,
  637.                                                   lMediaLeft,  lMediaRight);
  638.                                 // Compute the rest of the media rect
  639.                                 computeMeetSliceScaling(bIsMeet, 3,
  640.                                                         cRegPoint.x,
  641.                                                         lMediaLeft,
  642.                                                         cRegionRect.left,
  643.                                                         cRegPoint.y,
  644.                                                         cRegPoint.y - cMediaSize.cy,
  645.                                                         cRegionRect.top,
  646.                                                         cRegPoint.x,
  647.                                                         lMediaRight,
  648.                                                         cRegionRect.right,
  649.                                                         0, 0, 0,
  650.                                                         rcMediaRect.left,
  651.                                                         rcMediaRect.top,
  652.                                                         rcMediaRect.right,
  653.                                                         d);
  654.                             }
  655.                             break;
  656.                         case RegAlignBottomRight:
  657.                             {
  658.                                 // right and bottom are fixed
  659.                                 rcMediaRect.right  = cRegPoint.x;
  660.                                 rcMediaRect.bottom = cRegPoint.y;
  661.                                 // Compute the rest of the media rect
  662.                                 computeMeetSliceScaling(bIsMeet, 2,
  663.                                                         cRegPoint.x,
  664.                                                         cRegPoint.x - cMediaSize.cx,
  665.                                                         cRegionRect.left,
  666.                                                         cRegPoint.y,
  667.                                                         cRegPoint.y - cMediaSize.cy,
  668.                                                         cRegionRect.top,
  669.                                                         0, 0, 0, 0, 0, 0,
  670.                                                         rcMediaRect.left,
  671.                                                         rcMediaRect.top,
  672.                                                         d, d);
  673.                             }
  674.                             break;
  675.                     }
  676.                 }
  677.                 break;
  678.         }
  679.     }
  680.     else
  681.     {
  682.         retVal = HXR_FAIL;
  683.     }
  684.     return retVal;
  685. }
  686. void CSmilDocumentRenderer::computeHalfBounds(INT32 lMid, INT32 lSpan,
  687.                                               REF(INT32) rlMin, REF(INT32) rlMax)
  688. {
  689.     INT32 lHalfSpan = lSpan >> 1;
  690.     rlMin           = lMid - lHalfSpan;
  691.     rlMax           = lMid + (lSpan & 1 ? lHalfSpan + 1 : lHalfSpan);
  692. }
  693. void CSmilDocumentRenderer::computeFillHiddenScaling(Fit eFit, INT32 lRegPt, INT32 lMediaDim,
  694.                                                      INT32 lRegionLo, INT32 lRegionHi,
  695.                                                      REF(INT32) rlMediaLo,
  696.                                                      REF(INT32) rlMediaHi)
  697. {
  698.     // Get the min and max bounds of the media
  699.     INT32 lMediaLo = 0;
  700.     INT32 lMediaHi = 0;
  701.     computeHalfBounds(lRegPt, lMediaDim, lMediaLo, lMediaHi);
  702.     // Compute the rect
  703.     if (eFit == FitFill)
  704.     {
  705.         double dLoDiffOld  = lMediaLo  - lRegPt;
  706.         double dLoDiffNew  = lRegionLo - lRegPt;
  707.         double dHiDiffOld  = lMediaHi  - lRegPt;
  708.         double dHiDiffNew  = lRegionHi - lRegPt;
  709.         double dLoScale    = (dLoDiffOld != 0.0 ? dLoDiffNew / dLoDiffOld : 1.0);
  710.         double dHiScale    = (dHiDiffOld != 0.0 ? dHiDiffNew / dHiDiffOld : 1.0);
  711.         dLoScale           = (dLoScale > 0.0 ? dLoScale : -dLoScale);
  712.         dHiScale           = (dHiScale > 0.0 ? dHiScale : -dHiScale);
  713.         if (dLoScale != 0.0 && dLoScale < dHiScale)
  714.         {
  715.             rlMediaLo           = lRegionLo;
  716.             INT32 lScaledHiDiff = (INT32) (dHiDiffOld * dLoScale + 0.5);
  717.             rlMediaHi           = lRegPt + lScaledHiDiff;
  718.         }
  719.         else
  720.         {
  721.             INT32 lScaledLoDiff = (INT32) (dLoDiffOld * dHiScale + 0.5);
  722.             rlMediaLo           = lRegPt + lScaledLoDiff;
  723.             rlMediaHi           = lRegionHi;
  724.         }
  725.     }
  726.     else if (eFit == FitHidden ||
  727.              eFit == FitScroll)
  728.     {
  729.         rlMediaLo = lMediaLo;
  730.         rlMediaHi = lMediaHi;
  731.     }
  732. }
  733. void CSmilDocumentRenderer::computeMeetSliceScaling(BOOL   bIsMeet, UINT32 ulNumDim,
  734.                                                     INT32 lA1, INT32 lA2, INT32 lA3,
  735.                                                     INT32 lB1, INT32 lB2, INT32 lB3,
  736.                                                     INT32 lC1, INT32 lC2, INT32 lC3,
  737.                                                     INT32 lD1, INT32 lD2, INT32 lD3,
  738.                                                     REF(INT32) rlA, REF(INT32) rlB,
  739.                                                     REF(INT32) rlC, REF(INT32) rlD)
  740. {
  741.     // Make sure there's not more than 4 dimensions
  742.     if (ulNumDim > 4) ulNumDim = 4;
  743.     // Compute the scales
  744.     INT32  lBase[4]    = {lA1, lB1, lC1, lD1};
  745.     INT32  lOld[4]     = {lA2, lB2, lC2, lD2};
  746.     INT32  lNew[4]     = {lA3, lB3, lC3, lD3};
  747.     double dOldDiff[4] = {0.0, 0.0, 0.0, 0.0};
  748.     double dScale[4]   = {0.0, 0.0, 0.0, 0.0};
  749.     UINT32 i           = 0;
  750.     double dMinMax     = (bIsMeet ? 10000000.0 : 0.0);
  751.     for (i = 0; i < ulNumDim; i++)
  752.     {
  753.         // Compute the old diff
  754.         dOldDiff[i] = lOld[i] - lBase[i];
  755.         // Compute the new diff
  756.         double dNewDiff = lNew[i] - lBase[i];
  757.         // Compute the scale
  758.         dScale[i] = (dOldDiff[i] != 0 ? dNewDiff / dOldDiff[i] : 1.0);
  759.         // Make sure the scale is not negative
  760.         dScale[i] = (dScale[i] > 0.0 ? dScale[i] : -dScale[i]);
  761.         // Find the min or max
  762.         if ((bIsMeet  && dScale[i] < dMinMax) ||
  763.             (!bIsMeet && dScale[i] > dMinMax))
  764.         {
  765.             dMinMax = dScale[i];
  766.         }
  767.     }
  768.     // So now we have either the minimum or maximum scale,
  769.     // so now we need to adjust all of the scales to this scale
  770.     INT32 lOut[4] = {0, 0, 0, 0};
  771.     for (i = 0; i < ulNumDim; i++)
  772.     {
  773.         if (dScale[i] == dMinMax)
  774.         {
  775.             lOut[i] = lNew[i];
  776.         }
  777.         else
  778.         {
  779.             INT32 lNewDiff = (INT32) (dOldDiff[i] * dMinMax + 0.5);
  780.             lOut[i]        = lBase[i] + lNewDiff;
  781.         }
  782.     }
  783.     // Assign to the out parameters
  784.     rlA = lOut[0];
  785.     rlB = lOut[1];
  786.     rlC = lOut[2];
  787.     rlD = lOut[3];
  788. }
  789. HX_RESULT CSmilDocumentRenderer::processMediaRegionOverrides(const char* pszRegionID,
  790.                                                              const char* pszMediaID,
  791.                                                              BOOL        bMediaStart,
  792.                                                              UINT32      ulTime)
  793. {
  794.     HX_RESULT retVal = HXR_OK;
  795.     if (pszRegionID && pszMediaID)
  796.     {
  797.         // Get the source
  798.         CSmilSource* pSource = getSource(pszMediaID);
  799.         if (pSource)
  800.         {
  801.             // Get the region
  802.             CSmilBasicRegion* pRegion = getRegionByID(pszRegionID);
  803.             if (pRegion)
  804.             {
  805.                 // Are there any media overrides?
  806.                 if (pSource->m_bBackgroundColorSpecified)
  807.                 {
  808.                     // Get the site user
  809.                     UINT32         ulOldColor = 0;
  810.                     UINT32         ulNewColor = 0;
  811.                     CSmilSiteUser* pSiteUser  = (CSmilSiteUser*) pRegion->m_pSiteUser;
  812.                     if (pSiteUser)
  813.                     {
  814.                         // Are we starting or ending the media?
  815.                         if (bMediaStart)
  816.                         {
  817.                             // We are ending the media - therefore, we need to
  818.                             // set the site user's background color to the 
  819.                             // media's background color
  820.                             ulOldColor = pRegion->m_ulBackgroundColor;
  821.                             ulNewColor = pSource->m_ulBackgroundColor;
  822.                         }
  823.                         else
  824.                         {
  825.                             // We are ending the media - therefore, we need to
  826.                             // set the site user's background color to the 
  827.                             // region's background color
  828.                             ulOldColor = pSource->m_ulBackgroundColor;
  829.                             ulNewColor = pRegion->m_ulBackgroundColor;
  830.                         }
  831.                         // Now set the background color into the site user
  832.                         UINT32 ulCurColor = pSiteUser->GetBackgroundColor();
  833.                         if (ulCurColor != ulNewColor)
  834.                         {
  835.                             pSiteUser->SetBackgroundColor(ulNewColor);
  836.                             pSiteUser->Redraw();
  837.                         }
  838.                         // If the media is ending and we are resetting
  839.                         // the background Color back, then we should
  840.                         // note the time, so that an animation ending
  841.                         // will not reset it right back to what it is now.
  842.                         if (!bMediaStart)
  843.                         {
  844.                             pSiteUser->SetLastMediaEndOverrideTime(m_ulCurrentTime);
  845.                         }
  846.                     }
  847. #if 0
  848.                     // XXXMEH - TEST - this is a further optimization, but
  849.                     // seems to be blocked by a site bug. So ifdef
  850.                     // it out for now.
  851.                     // Check if we need to adjust the "SiteNeverBlts"
  852.                     // property of the site. If we are switching to or
  853.                     // from totally transparent, then we may need to
  854.                     // adjust this property
  855.                     if (isTransparent(ulNewColor) &&
  856.                         !isTransparent(ulOldColor))
  857.                     {
  858.                         setSiteProperty(pRegion->m_pSite, "SiteNeverBlts", "1");
  859.                     }
  860.                     else if (!isTransparent(ulNewColor) &&
  861.                              isTransparent(ulOldColor))
  862.                     {
  863.                         setSiteProperty(pRegion->m_pSite, "SiteNeverBlts", "0");
  864.                     }
  865. #endif
  866.                 }
  867. #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT)
  868.                 // Now we need to check if this media is playing
  869.                 // to a viewport.
  870.                 if (!pRegion->m_bUnderRootLayout)
  871.                 {
  872.                     // This media is playing to a viewport,
  873.                     // so get the viewport.
  874.                     CSmilBasicViewport* pPort = getViewportByDescendant(pRegion);
  875.                     if (pPort)
  876.                     {
  877.                         // Check whether we need to increment or
  878.                         // decrement the active media count.
  879.                         if (bMediaStart)
  880.                         {
  881.                             // Media is starting, so increment the
  882.                             // active media count
  883.                             pPort->m_ulNumActiveMedia++;
  884.                             // If this is the first media to start AND
  885.                             // the viewport has an "open" property of
  886.                             // whenActive, then do a show on the viewport
  887.                             if (pPort->m_ulNumActiveMedia == 1 &&
  888.                                 pPort->m_pPort                 &&
  889.                                 pPort->m_pPort->m_eOpen == ViewportOpenWhenActive)
  890.                             {
  891.                                 showHideViewport(pPort, TRUE);
  892.                             }
  893.                         }
  894.                         else
  895.                         {
  896.                             // Media is ending or being hidden, so
  897.                             // decrement the active media count, but 
  898.                             // make sure we don't wrap around
  899.                             if (pPort->m_ulNumActiveMedia)
  900.                             {
  901.                                 pPort->m_ulNumActiveMedia--;
  902.                             }
  903.                             // If this is the last media to end AND
  904.                             // the viewport has a "close" property of
  905.                             // whenNotActive, then do a hide on the viewport.
  906.                             if (pPort->m_ulNumActiveMedia == 0 &&
  907.                                 pPort->m_pPort                 &&
  908.                                 pPort->m_pPort->m_eClose == ViewportCloseWhenNotActive)
  909.                             {
  910.                                 showHideViewport(pPort, FALSE);
  911.                             }
  912.                         }
  913.                     }
  914.                 }
  915. #endif /* #if defined(HELIX_FEATURE_SMIL2_MULTIWINDOWLAYOUT) */
  916.                 // Now we need to check whether the starting or ending
  917.                 // if this media will cause a parent region to display.
  918.                 // For instance, if region B is a child of region A,
  919.                 // and region A has showBackground="whenActive", then
  920.                 // region A may NOT be visible when media in region B
  921.                 // starts. However, "whenActive" means that when media
  922.                 // is active in the region OR ANY CHILD REGIONS. Therefore,
  923.                 // region A should be made visible at the same time.
  924.                 // Conversely, if a media is ending, it may cause a parent
  925.                 // to be hidden.
  926.                 //
  927.                 // Loop up through the region's ancestors. We
  928.                 // can know if the CSmilBasicBox is a CSmilBasicRegion
  929.                 // by the fact that top-level boxes will have 
  930.                 // no parents, so if CSmilBasicBox::m_pParent == NULL,
  931.                 // then it's a top-level box and not a region.
  932.                 CSmilBasicBox* pBox = pRegion->m_pParent;
  933.                 while (pBox && pBox->m_pParent)
  934.                 {
  935.                     // We know this is a region, so cast it
  936.                     CSmilBasicRegion* pParReg = (CSmilBasicRegion*) pBox;
  937.                     // Are we starting or ending this media?
  938.                     if (bMediaStart)
  939.                     {
  940.                         // We are starting this media, so we need
  941.                         // to check if this region has showBackground="whenActive".
  942.                         // If it does, then we need to show this site.
  943.                         if (pParReg->m_eShowBackground == ShowBackgroundWhenActive)
  944.                         {
  945.                             showSite(pParReg->m_pSite, TRUE);
  946.                         }
  947.                     }
  948.                     else
  949.                     {
  950.                         // We are ending this media, so we need to
  951.                         // check two things: a) does this region have 
  952.                         // showBackground="whenActive"; and b) is anything
  953.                         // currently playing in this region at this time?
  954.                         // If (a) is yes and (b) is no, then we need to
  955.                         // hide this site.
  956.                         if (pParReg->m_eShowBackground == ShowBackgroundWhenActive &&
  957.                             !isRegionActive(pParReg->m_region, (UINT16) m_uCurrentGroupIndex, ulTime))
  958.                         {
  959.                             showSite(pParReg->m_pSite, FALSE);
  960.                         }
  961.                     }
  962.                     // Get the next ancestor up
  963.                     pBox = pBox->m_pParent;
  964.                 }
  965.                 // We need to resolve the z-order every time media starts
  966.                 // or stops. We only need to resolve from the region's parent
  967.                 // down.
  968.                 resolveZOrder(pRegion->m_pParent, ulTime);
  969.             }
  970.         }
  971.     }
  972.     return retVal;
  973. }
  974. void CSmilDocumentRenderer::resolveZOrder(CSmilBasicBox* pBox, UINT32 ulTime)
  975. {
  976.     // Resolving z-order is really resolving z-order among our
  977.     // children, so if we don't have any children, then there's
  978.     // nothing to do.
  979.     if (pBox)
  980.     {
  981.         // Get the site for this box. This could be a region site
  982.         // or it could be the root-level site.
  983.         IHXSite* pBoxSite = pBox->m_pSite;
  984.         if (pBoxSite)
  985.         {
  986.             // There can be two kinds of child sites of this site - 
  987.             // region sites and renderer sites. All the child renderer sites
  988.             // must be lower in z-order than the child region sites.
  989.             // So we must sort them first.
  990.             INT32         lCurZOrder = 0;
  991.             CHXSimpleList cTmpList;
  992.             // Run through the site info list and pick out renderer
  993.             // sites which are playing to this region site (potentially
  994.             // more than one). Note that if this is a root-level
  995.             // site, then there won't be any renderers playing to this
  996.             // site.
  997.             if (m_pSiteInfoList)
  998.             {
  999.                 LISTPOSITION pos = m_pSiteInfoList->GetHeadPosition();
  1000.                 while (pos)
  1001.                 {
  1002.                     SMILSiteInfo* pInfo = (SMILSiteInfo*) m_pSiteInfoList->GetNext(pos);
  1003.                     if (pInfo && pInfo->m_pRegionSite == pBoxSite)
  1004.                     {
  1005. // /Helps fix PR 81510 (& duplicate PR 83796); if delay
  1006. // < resume time, use resume time for z-ordering:
  1007. UINT32 ulRelevantInfoDelay = pInfo->m_ulDelay;
  1008. if (pInfo->m_ulResumeTime > pInfo->m_ulDelay)
  1009. {
  1010.     ulRelevantInfoDelay = pInfo->m_ulResumeTime;
  1011. }
  1012.                         // This is a renderer playing to this region, so add it
  1013.                         // to the list in the proper order (increasing by begin
  1014.                         // time, begin-time tie-breaker by lexical order)
  1015.                         BOOL         bAdded = FALSE;
  1016.                         LISTPOSITION pos2   = cTmpList.GetHeadPosition();
  1017.                         while (pos2)
  1018.                         {
  1019.                             SMILSiteInfo* pListInfo = (SMILSiteInfo*) cTmpList.GetAt(pos2);
  1020.                             if (pListInfo)
  1021.                             {
  1022. UINT32 ulRelevantListInfoDelay = pListInfo->m_ulDelay;
  1023. if (pListInfo->m_ulResumeTime > pListInfo->m_ulDelay)
  1024. {
  1025.     ulRelevantListInfoDelay = pListInfo->m_ulResumeTime;
  1026. }
  1027.                                 if (pListInfo->m_lZIndex > pInfo->m_lZIndex ||
  1028.                                     ulRelevantListInfoDelay > ulRelevantInfoDelay ||
  1029.                                     (ulRelevantListInfoDelay  == ulRelevantInfoDelay &&
  1030.                                      pListInfo->m_ulLexicalOrder >  pInfo->m_ulLexicalOrder))
  1031.                                 {
  1032.                                     cTmpList.InsertBefore(pos2, (void*) pInfo);
  1033.                                     bAdded = TRUE;
  1034.                                     break;
  1035.                                 }
  1036.                             }
  1037.                             cTmpList.GetNext(pos2);
  1038.                         }
  1039.                         if (!bAdded)
  1040.                         {
  1041.                             cTmpList.AddTail((void*) pInfo);
  1042.                         }
  1043.                     }
  1044.                 }
  1045.                 // Now we have ordered the renderer sites, we can
  1046.                 // set the z-order of the renderer sites
  1047.                 pos = cTmpList.GetHeadPosition();
  1048.                 while (pos)
  1049.                 {
  1050.                     SMILSiteInfo* pInfo = (SMILSiteInfo*) cTmpList.GetNext(pos);
  1051.                     if (pInfo)
  1052.                     {
  1053.                         setSiteZIndex(pInfo->m_pRendererSite, lCurZOrder++);
  1054.                     }
  1055.                 }
  1056.                 // Now we can clear the temporary list
  1057.                 cTmpList.RemoveAll();
  1058.             }
  1059.             // After those, we have to order the region sites which may
  1060.             // be children of this site. We know that these must be
  1061.             // CSmilBasicRegion's.
  1062.             if (pBox->m_pChildList)
  1063.             {
  1064.                 LISTPOSITION pos = pBox->m_pChildList->GetHeadPosition();
  1065.                 while (pos)
  1066.                 {
  1067.                     CSmilBasicRegion* pRegion =
  1068.                         (CSmilBasicRegion*) pBox->m_pChildList->GetNext(pos);
  1069.                     if (pRegion)
  1070.                     {
  1071.                         // Now insert this into the z-order list
  1072.                         BOOL         bAdded = FALSE;
  1073.                         LISTPOSITION pos2   = cTmpList.GetHeadPosition();
  1074.                         while (pos2)
  1075.                         {
  1076.                             CSmilBasicRegion* pListRegion = 
  1077.                                 (CSmilBasicRegion*) cTmpList.GetAt(pos2);
  1078.                             if (pListRegion)
  1079.                             {
  1080.                                 if (pListRegion->m_lZIndex > pRegion->m_lZIndex)
  1081.                                 {
  1082.                                     cTmpList.InsertBefore(pos2, (void*) pRegion);
  1083.                                     bAdded = TRUE;
  1084.                                     break;
  1085.                                 }
  1086.                                 else if (pListRegion->m_lZIndex == pRegion->m_lZIndex)
  1087.                                 {
  1088.                                     UINT32    ulListStartTime    = 0;
  1089.                                     UINT32    ulListLexicalOrder = 0;
  1090.                                     HX_RESULT lListRet           = getMostRecentInfo(pListRegion->m_pSite,
  1091.                                                                                      ulTime,
  1092.                                                                                      ulListStartTime,
  1093.                                                                                      ulListLexicalOrder);
  1094.                                     if (SUCCEEDED(lListRet))
  1095.                                     {
  1096.                                         UINT32    ulStartTime    = 0;
  1097.                                         UINT32    ulLexicalOrder = 0;
  1098.                                         HX_RESULT lRet           = getMostRecentInfo(pRegion->m_pSite,
  1099.                                                                                      ulTime,
  1100.                                                                                      ulStartTime,
  1101.                                                                                      ulLexicalOrder);
  1102.                                         if (SUCCEEDED(lRet))
  1103.                                         {
  1104.                                             if (ulListStartTime > ulStartTime ||
  1105.                                                 (ulListStartTime    == ulStartTime &&
  1106.                                                  ulListLexicalOrder >  ulLexicalOrder))
  1107.                                             {
  1108.                                                 cTmpList.InsertBefore(pos2, (void*) pRegion);
  1109.                                                 bAdded = TRUE;
  1110.                                                 break;
  1111.                                             }
  1112.                                         }
  1113.                                     }
  1114.                                 }
  1115.                             }
  1116.                             cTmpList.GetNext(pos2);
  1117.                         }
  1118.                         if (!bAdded)
  1119.                         {
  1120.                             cTmpList.AddTail((void*) pRegion);
  1121.                         }
  1122.                     }
  1123.                 }
  1124.                 // Now that we have ordered the child region sites,
  1125.                 // we can go through and continue setting the z-index.
  1126.                 pos = cTmpList.GetHeadPosition();
  1127.                 while (pos)
  1128.                 {
  1129.                     CSmilBasicRegion* pRegion = (CSmilBasicRegion*) cTmpList.GetNext(pos);
  1130.                     if (pRegion)
  1131.                     {
  1132.                         setSiteZIndex(pRegion->m_pSite, lCurZOrder++);
  1133.                     }
  1134.                 }
  1135.                 // Now we can clear the temporary list
  1136.                 cTmpList.RemoveAll();
  1137.                 // Now we must recursively call this method on
  1138.                 // all the children
  1139.                 pos = pBox->m_pChildList->GetHeadPosition();
  1140.                 while (pos)
  1141.                 {
  1142.                     CSmilBasicBox* pChildBox = (CSmilBasicBox*) pBox->m_pChildList->GetNext(pos);
  1143.                     resolveZOrder(pChildBox, ulTime);
  1144.                 }
  1145.             }
  1146.         }
  1147.     }
  1148. }
  1149. HX_RESULT CSmilDocumentRenderer::getMostRecentInfo(IHXSite* pSite, UINT32 ulTime,
  1150.                                                    REF(UINT32) rulStartTime,
  1151.                                                    REF(UINT32) rulLexicalOrder)
  1152. {
  1153.     HX_RESULT retVal = HXR_OK;
  1154.     // Clear flag which says we found anything
  1155.     BOOL   bFoundOne = FALSE;
  1156.     UINT32 ulStart   = 0;
  1157.     UINT32 ulLexical = 0;
  1158.     // Run through the site info list
  1159.     if (pSite && m_pSiteInfoList)
  1160.     {
  1161.         LISTPOSITION pos = m_pSiteInfoList->GetHeadPosition();
  1162.         while (pos)
  1163.         {
  1164.             SMILSiteInfo* pInfo = (SMILSiteInfo*) m_pSiteInfoList->GetNext(pos);
  1165.     // /Helps fix PR 81510 (& duplicate PR 83796); if delay is less than
  1166.     // resume time, use resume time as if it were start time:
  1167.     UINT32 ulRelevantDelay = pInfo->m_ulDelay;
  1168.     if (pInfo->m_ulResumeTime > pInfo->m_ulDelay)
  1169.     {
  1170. ulRelevantDelay = pInfo->m_ulResumeTime;
  1171.     }
  1172.             if (pInfo                         &&
  1173.                 pInfo->m_pRegionSite == pSite &&
  1174.                 ulTime               >= ulRelevantDelay)
  1175.             {
  1176.                 if (!bFoundOne)
  1177.                 {
  1178.                     ulStart   = ulRelevantDelay;
  1179.                     ulLexical = pInfo->m_ulLexicalOrder;
  1180.                     bFoundOne = TRUE;
  1181.                 }
  1182.                 else
  1183.                 {
  1184.                     if (ulRelevantDelay > ulStart ||
  1185.                         (ulRelevantDelay        == ulStart &&
  1186.                          pInfo->m_ulLexicalOrder >  ulLexical))
  1187.                     {
  1188.                         ulStart   = ulRelevantDelay;
  1189.                         ulLexical = pInfo->m_ulLexicalOrder;
  1190.                     }
  1191.                 }
  1192.             }
  1193.         }
  1194.     }
  1195.     // Assign the out parameters
  1196.     if (bFoundOne)
  1197.     {
  1198.         rulStartTime    = ulStart;
  1199.         rulLexicalOrder = ulLexical;
  1200.     }
  1201.     else
  1202.     {
  1203.         retVal = HXR_FAIL;
  1204.     }
  1205.     return retVal;
  1206. }
  1207. void CSmilDocumentRenderer::addStringProperty(IHXValues* pValues,
  1208.                                               IUnknown*   pContext,
  1209.                                               const char* pszName,
  1210.                                               const char* pszValue)
  1211. {
  1212.     if (pValues && pContext && pszName && pszValue)
  1213.     {
  1214.         IHXCommonClassFactory* pFact = NULL;
  1215.         pContext->QueryInterface(IID_IHXCommonClassFactory, (void**) &pFact);
  1216.         if (pFact)
  1217.         {
  1218.             IHXBuffer* pBuf = NULL;
  1219.             pFact->CreateInstance(CLSID_IHXBuffer, (void**) &pBuf);
  1220.             if (pBuf)
  1221.             {
  1222.                 HX_RESULT rv = pBuf->Set((const UCHAR*) pszValue, strlen(pszValue) + 1);
  1223.                 if (SUCCEEDED(rv))
  1224.                 {
  1225.                     pValues->SetPropertyCString(pszName, pBuf);
  1226.                 }
  1227.             }
  1228.             HX_RELEASE(pBuf);
  1229.         }
  1230.         HX_RELEASE(pFact);
  1231.     }
  1232. }
  1233. BOOL CSmilDocumentRenderer::hasParamChildren(CSmilElement* pElement,
  1234.                                              BOOL          bServerOnly)
  1235. {
  1236.     BOOL bRet = FALSE;
  1237.     if (pElement && pElement->m_pNode)
  1238.     {
  1239.         SMILNode* pChild = pElement->m_pNode->getFirstChild();
  1240.         while (pChild)
  1241.         {
  1242.             if (pChild->m_tag == SMILParam)
  1243.             {
  1244.                 if (bServerOnly)
  1245.                 {
  1246.                     CSmilParamElement* pParam = (CSmilParamElement*) pChild->m_pElement;
  1247.                     if (pParam &&
  1248.                         pParam->m_eDelivery == DeliveryServer)
  1249.                     {
  1250.                         bRet = TRUE;
  1251.                         break;
  1252.                     }
  1253.                 }
  1254.                 else
  1255.                 {
  1256.                     bRet = TRUE;
  1257.                     break;
  1258.                 }
  1259.             }
  1260.             pChild = pElement->m_pNode->getNextChild();
  1261.         }
  1262.     }
  1263.     return bRet;
  1264. }
  1265. void CSmilDocumentRenderer::addParamProperties(CSmilElement* pElement,
  1266.                                                IHXValues*   pValues,
  1267.                                                IUnknown*     pContext,
  1268.                                                BOOL          bServerOnly)
  1269. {
  1270.     if (pElement && pElement->m_pNode && pValues && pContext)
  1271.     {
  1272.         SMILNode* pChild = pElement->m_pNode->getFirstChild();
  1273.         while (pChild)
  1274.         {
  1275.             if (pChild->m_tag == SMILParam && pChild->m_pElement)
  1276.             {
  1277.                 CSmilParamElement* pParam = (CSmilParamElement*) pChild->m_pElement;
  1278.                 if (pParam->m_pName &&
  1279.                     pParam->m_pValue &&
  1280.                     ((bServerOnly && pParam->m_eDelivery == DeliveryServer) || !bServerOnly))
  1281.                 {
  1282.                     pValues->SetPropertyCString((const char*) pParam->m_pName->GetBuffer(),
  1283.                                                 pParam->m_pValue);
  1284.                 }
  1285.             }
  1286.             pChild = pElement->m_pNode->getNextChild();
  1287.         }
  1288.     }
  1289. }
  1290. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  1291. void CSmilDocumentRenderer::checkAnimChildren(CSmilElement* pElement, UINT32 ulTrackEnd)
  1292. {
  1293.     if (pElement && pElement->m_pNode)
  1294.     {
  1295.         SMILNode* pChild = pElement->m_pNode->getFirstChild();
  1296.         while (pChild)
  1297.         {
  1298.             if (pChild->m_tag == SMILAnimate       ||
  1299.                 pChild->m_tag == SMILAnimateMotion ||
  1300.                 pChild->m_tag == SMILAnimateColor  ||
  1301.                 pChild->m_tag == SMILAnimateMotion)
  1302.             {
  1303.                 CSmilAnimateElement* pAnim =
  1304.                     (CSmilAnimateElement*) pChild->m_pElement;
  1305.                 if (pAnim)
  1306.                 {
  1307.                     if (pAnim->m_ulDelay >= ulTrackEnd)
  1308.                     {
  1309.                         // Our parent totally prevents us from
  1310.                         // starting. Since the event is probably
  1311.                         // already scheduled, then we will simply
  1312.                         // mark this to cancel this animation
  1313.                         pAnim->m_bCancelAnimation = TRUE;
  1314.                     }
  1315.                     else if (pAnim->m_ulDelay < ulTrackEnd &&
  1316.                              pAnim->m_ulDelay + pAnim->m_ulActiveDuration > ulTrackEnd)
  1317.                     {
  1318.                         // The delay is less than the track end, but
  1319.                         // the delay plus active duration is cut off
  1320.                         // by the track end. Therefore, we will shorten
  1321.                         // the active duration to match the track end.
  1322.                         pAnim->m_ulActiveDuration = ulTrackEnd - pAnim->m_ulDelay;
  1323.                     }
  1324.                 }
  1325.             }
  1326.             pChild = pElement->m_pNode->getNextChild();
  1327.         }
  1328.     }
  1329. }
  1330. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  1331. #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
  1332. CSmilTransitionInfo::CSmilTransitionInfo(CSmilTransition* pTrans, 
  1333.                                          IUnknown*        pContext)
  1334. {
  1335.     HX_ASSERT(pTrans);
  1336.     HX_ASSERT(pContext);
  1337.     m_pTrans   = pTrans;
  1338.     m_pContext = pContext;
  1339.     if (m_pContext)
  1340.     {
  1341.         // AddRef the context
  1342.         m_pContext->AddRef();
  1343.     }
  1344. }
  1345. CSmilTransitionInfo::~CSmilTransitionInfo()
  1346. {
  1347.     HX_RELEASE(m_pContext);
  1348. }
  1349. #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
  1350. // /IHXClientAdviseSink Interface Methods:
  1351. STDMETHODIMP
  1352. CSmilDocumentRenderer::OnPosLength(UINT32   ulPosition,
  1353.    UINT32   ulLength)
  1354. {
  1355.     MLOG_TIMESYNC(m_pErrorMessages, "OnPosLength(%lu,%lu) tick=%lun",
  1356.                   ulPosition, ulLength, HX_GET_BETTERTICKCOUNT());
  1357.     // /Note: this *should* have been done in OnBuffering() when 100%
  1358.     // was complete, but the renderers don't get a chance to draw until
  1359.     // after OnBuffering(100%) is done, apparently:
  1360.     if (ulPosition > 0  &&  m_bDestPlaystateIsPause)
  1361.     {
  1362. // /Done buffering, and we've had a chance to draw the first "frame"
  1363. // of each media stream's data, so let's pause it if
  1364. // "destinationPlaystate" was "pause":
  1365. IHXPlayer* pPlayer = m_pParent->getPlayer();
  1366. if(pPlayer)
  1367. {
  1368.     pPlayer->Pause();
  1369. }
  1370. m_bDestPlaystateIsPause = FALSE;
  1371.     }
  1372.     // The ulLength argument is the current duration
  1373.     // of the current group. Save this value
  1374.     m_ulCurGroupDuration = ulLength;
  1375.     return HXR_OK;
  1376. }
  1377. STDMETHODIMP
  1378. CSmilDocumentRenderer::OnPresentationOpened()
  1379. {
  1380.     return HXR_NOTIMPL;
  1381. }
  1382. STDMETHODIMP
  1383. CSmilDocumentRenderer::OnPresentationClosed()
  1384. {
  1385. // /   HX_ASSERT(0=="XXXEH: implementThis!");
  1386.     // /When we get this notification, we need to decide whether or not
  1387.     // the caller of this is the player we were playing in or a new
  1388.     // player that opened (and may mean we're in a paused state):
  1389.     return HXR_NOTIMPL;
  1390. }
  1391. STDMETHODIMP
  1392. CSmilDocumentRenderer::OnStatisticsChanged(void)
  1393. {
  1394.     return HXR_NOTIMPL;
  1395. }
  1396. STDMETHODIMP
  1397. CSmilDocumentRenderer::OnPreSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  1398. {
  1399.     return HXR_NOTIMPL;
  1400. }
  1401. STDMETHODIMP
  1402. CSmilDocumentRenderer::OnPostSeek(UINT32 ulOldTime, UINT32 ulNewTime)
  1403. {
  1404.     return HXR_NOTIMPL;
  1405. }
  1406. STDMETHODIMP
  1407. CSmilDocumentRenderer::OnStop(void)
  1408. {
  1409.     return HXR_NOTIMPL;
  1410. }
  1411. STDMETHODIMP
  1412. CSmilDocumentRenderer::OnPause(UINT32 ulTime)
  1413. {
  1414.     return HXR_NOTIMPL;
  1415. }
  1416. // Called by client engine to inform that a begin OR resume has just occured:
  1417. STDMETHODIMP
  1418. CSmilDocumentRenderer::OnBegin(UINT32 ulTime)
  1419. {
  1420.     // /First, if we have a fragment offset in the URL that we're playing,
  1421.     // now is the time to do the seek of the player since it isn't ready
  1422.     // to be seeked until this point:
  1423.     IHXPlayer* pPlayer = m_pParent->getPlayer();
  1424.     HX_ASSERT(pPlayer);
  1425.     //If getFragmentOffset() found the fragment and it had
  1426.     // a resolved begin time (plus offset) of zero,
  1427.     // we used to not seek to 0 even though that's a valid
  1428.     // value.
  1429.     // (Note: this problem was found while fixing PR 22655.)
  1430.     if(pPlayer  &&  m_bFragFoundAndResolved)
  1431.     {
  1432. pPlayer->Seek(m_ulFragmentTimeOffset);
  1433.     }
  1434.     return HXR_OK;
  1435. }
  1436. // Called by client engine to inform the client that buffering
  1437. // of data is occuring. The render is informed of the reason for
  1438. // the buffering (start-up of stream, seek has occured, network
  1439. // congestion, etc.), as well as percentage complete of the 
  1440. // buffering process.
  1441. STDMETHODIMP
  1442. CSmilDocumentRenderer::OnBuffering(UINT32 ulFlags, UINT16 unPercentComplete)
  1443. {
  1444.     // /Note: deciding on whether or not to pause *should* have been
  1445.     // done here when 100% was complete, but the renderers don't get
  1446.     // a chance to draw until after OnBuffering(100%) is done, apparently,
  1447.     // so the code to handle this is in OnPosLength().
  1448.     return HXR_NOTIMPL;
  1449. }
  1450. /****************************************************************************
  1451.  *  IHXClientAdviseSink::OnContacting                       ref:  hxclsnk.h
  1452.  *
  1453.  *  Called by client engine to inform the client is contacting hosts(s).
  1454.  */
  1455. STDMETHODIMP
  1456. CSmilDocumentRenderer::OnContacting(const char* pHostName)
  1457. {
  1458.     return HXR_NOTIMPL;
  1459. }
  1460. HX_RESULT
  1461. CSmilDocumentRenderer::GetElementProperties(UINT16 uGroupID, 
  1462.     UINT16 uTrackID, 
  1463.     REF(IHXValues*) pProperties)
  1464. {
  1465.     HX_RESULT rc = HXR_OK;
  1466.     CSmilElement* pElement = NULL;
  1467.     pProperties = NULL;
  1468.     SMILPlayToAssoc* pPlayToAssoc = getPlayToAssoc(uGroupID, uTrackID);
  1469.     if (pPlayToAssoc)
  1470.     {
  1471. pElement = m_pSmilParser->findElement(pPlayToAssoc->m_id);
  1472. if (pElement)
  1473. {
  1474.     rc = pElement->GetElementProperties(pProperties);
  1475. }
  1476.     }
  1477.     return rc;
  1478. }
  1479. HX_RESULT  
  1480. CSmilDocumentRenderer::GetElementStatus(UINT16     uGroupID,
  1481.         UINT16     uTrackID,
  1482.         UINT32     ulCurrentTime,
  1483.         REF(IHXValues*)    pStatus)
  1484. {
  1485.     HX_RESULT rc = HXR_OK;
  1486.     CHXSimpleList* pSiteInfoList = NULL;
  1487.     CSmilElement* pElement = NULL;
  1488.     CSmilShowSiteEvent* pCurHideEvent = NULL;
  1489.     SMILPlayToAssoc* pPlayToAssoc = getPlayToAssoc(uGroupID, uTrackID);
  1490.     pStatus = NULL;
  1491.     if (pPlayToAssoc && pPlayToAssoc->m_pSiteInfoList)
  1492.     {
  1493. pSiteInfoList = pPlayToAssoc->m_pSiteInfoList;
  1494.         LISTPOSITION pos = pSiteInfoList->GetHeadPosition();
  1495.         while (pos)
  1496.         {
  1497.             SMILSiteInfo* pSiteInfo = (SMILSiteInfo*)pSiteInfoList->GetNext(pos);
  1498.             if (pSiteInfo)
  1499.             {
  1500. pCurHideEvent = getShowHideEvent(pPlayToAssoc->m_id,
  1501.                                                  pSiteInfo->m_regionID,
  1502.                                                  FALSE);
  1503. if (pCurHideEvent && pCurHideEvent->m_ulEventTime > ulCurrentTime)
  1504. {
  1505.     pStatus = new CHXHeader();
  1506.     pStatus->AddRef();
  1507.     pStatus->SetPropertyULONG32("Show", 1);
  1508.     break;
  1509. }
  1510.     }
  1511. }
  1512.     }
  1513.     return rc;
  1514. }
  1515. HX_RESULT
  1516. CSmilDocumentRenderer::AttachElementLayout(UINT16     uGroupID,
  1517.    UINT16     uTrackID,
  1518.    IHXRenderer*    pRenderer,
  1519.    IHXStream*     pStream,
  1520.    IHXValues*     pProps)
  1521. {
  1522.     HX_RESULT rc = HXR_OK;    
  1523.     UINT32 ulDelay = 0;
  1524.     UINT32 ulDuration = 0;
  1525.     IHXLayoutStream* pLayoutStream = NULL;
  1526.     CSmilBasicRegion* pRegion = NULL;
  1527.     CHXSimpleList* pRendererList = NULL;
  1528.     SMILSourceInfo* pSourceInfo = NULL;
  1529.     SMILPlayToAssoc* pPlayToAssoc = NULL;
  1530.     // setup the Root layout if it has not
  1531.     // this could happen when the child SMIL gets initialized 
  1532.     // ahead of its parent when switching groups
  1533.     if (m_bSitesDetached)
  1534.     {
  1535. m_bSitesDetached = FALSE;
  1536. rc = setupRootLayout(FALSE);
  1537. HX_ASSERT(HXR_OK == rc);
  1538.     }
  1539.     pPlayToAssoc = getPlayToAssoc(uGroupID, uTrackID);
  1540.     HX_ASSERT(pPlayToAssoc);
  1541.     pRegion = getRegionByID(pPlayToAssoc->m_playTo);    
  1542.     if (!pRegion)
  1543.     {
  1544. // We didn't find a <region> by id and we 
  1545. // didn't find a <region> by the "regionName"
  1546. // indirection, so we are going to have to 
  1547. // fall back to the "default" region.
  1548. pRegion = setupDefaultLayout();
  1549. if (pRegion)
  1550. {
  1551.     // Change the parameters
  1552.     pPlayToAssoc->m_playTo     = pRegion->m_region;
  1553.     pPlayToAssoc->m_regionName = pRegion->m_region;
  1554. }
  1555.     }
  1556.     // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  1557.     // /XXXEH- To do: the code inside this if() and the code after the else is
  1558.     // the same code (reordered a bit) as found inside RendererInitialized(),
  1559.     // above.  To do: Combine into a function noting that the following also
  1560.     // calls HandleAttachElementLayout(), not done in RendererInitialized():
  1561.     if (pStream && pProps)
  1562.     {
  1563. pSourceInfo = new SMILSourceInfo;
  1564. pSourceInfo->m_pStream = pStream;
  1565. if(pSourceInfo->m_pStream)
  1566. {
  1567.     pSourceInfo->m_pStream->AddRef();
  1568. }
  1569. pSourceInfo->m_pRenderer = pRenderer;
  1570. if(pSourceInfo->m_pRenderer)
  1571. {
  1572.     pSourceInfo->m_pRenderer->AddRef();
  1573. }
  1574.     
  1575. pProps->GetPropertyULONG32("Delay", ulDelay);
  1576. pProps->GetPropertyULONG32("Duration", ulDuration);
  1577. pSourceInfo->m_ulDelay = ulDelay;
  1578. pSourceInfo->m_ulDuration = ulDuration - ulDelay;
  1579. pRendererList = (CHXSimpleList*) pPlayToAssoc->m_sourceMap[0];
  1580. HX_ASSERT(pRendererList);
  1581. // /Check for NULL as happens in PR 120999 when jumping back
  1582. // and forth between clips in a clip list:
  1583. if (pRendererList)
  1584. {
  1585.     pRendererList->AddTail(pSourceInfo);
  1586. }
  1587.     }
  1588.     else
  1589.     {
  1590. pRendererList = (CHXSimpleList*)pPlayToAssoc->m_sourceMap[0];
  1591. HX_ASSERT(pRendererList->GetCount() == 1);
  1592. pSourceInfo = (SMILSourceInfo*)pRendererList->GetHead();
  1593.     }
  1594.     char cTemp[20]; /* Flawfinder: ignore */
  1595.     ::sprintf(cTemp,"%#010lx",(ULONG32)(void*)pRenderer); /* Flawfinder: ignore */
  1596.     pSourceInfo->m_tunerName   = (const char*) cTemp;
  1597.     ::sprintf(cTemp,"%#010lx",(ULONG32)(void*)pRenderer+1); /* Flawfinder: ignore */
  1598.     pSourceInfo->m_childTunerName = (const char*)cTemp;
  1599.     const char* pChildTuner = pSourceInfo->m_childTunerName;
  1600.     // get to the site manager and set an event hook
  1601.     IHXEventHookMgr* pHookMgr = NULL;
  1602.     if(HXR_OK ==
  1603. m_pSiteMgr->QueryInterface(IID_IHXEventHookMgr, 
  1604. (void**)&pHookMgr))
  1605.     {
  1606. CSmilEventHook* pChildEventHook = NULL;
  1607. // create event hook for playto
  1608. pChildEventHook = new CSmilEventHook((CSmilEventHookResponse*) this,
  1609.      pPlayToAssoc->m_playTo, pChildTuner, FALSE,
  1610.      (const char*) pPlayToAssoc->m_id);
  1611. pChildEventHook->AddRef();
  1612. pHookMgr->AddHook(pChildEventHook, pChildTuner, 0);
  1613. pSourceInfo->m_pRendererEventHook = pChildEventHook;
  1614. pHookMgr->Release();
  1615.     }
  1616.     else
  1617.     {
  1618. pSourceInfo->m_pRendererEventHook = NULL;
  1619.     }
  1620.     pPlayToAssoc->m_tunerName = pSourceInfo->m_tunerName;
  1621.     pPlayToAssoc->m_childTunerName = pSourceInfo->m_childTunerName;
  1622.     pPlayToAssoc->m_pRendererEventHook = pSourceInfo->m_pRendererEventHook;
  1623.     // add hyperlinks
  1624.     CSmilElement* pElement = m_pSmilParser->findElement(
  1625. pPlayToAssoc->m_id);
  1626.     if(pElement && pElement->m_pHyperlinks)
  1627.     {
  1628. CHXSimpleList::Iterator i = 
  1629. pElement->m_pHyperlinks->Begin();
  1630. for(; i != pElement->m_pHyperlinks->End(); ++i)
  1631. {
  1632.     CSmilAAnchorElement* pAnchor = 
  1633. (CSmilAAnchorElement*)(*i);
  1634.     //[SMIL 1.0 Compliance] Fixes PR 26473:
  1635.     // We want to add in LIFO fashion so inner
  1636.     // (nested) anchors will be found first in
  1637.     // CSmilDocumentRenderer::findHyperlinkElement(),
  1638.     // below.  In other words, we're giving an
  1639.     // effective higher link "z-order" to the
  1640.     // decendants of other links.  This used to
  1641.     // call AddTail():
  1642.     pPlayToAssoc->m_pHyperlinks->AddHead(pAnchor);
  1643. }
  1644.     }
  1645.     IHXValues* pValues = 0;
  1646.     IHXBuffer* pPlayToBuffer = 0;
  1647.     IHXBuffer* pRegionName = 0;
  1648.     IHXCommonClassFactory* pFactory = m_pParent->getFactory();
  1649.     if ((HXR_OK == pFactory->CreateInstance(CLSID_IHXValues, (void**)&pValues)) &&
  1650. (HXR_OK == pFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pPlayToBuffer)) &&
  1651. (HXR_OK == pFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pRegionName)))
  1652.     {     
  1653. pPlayToBuffer->Set((BYTE*)pChildTuner, strlen(pChildTuner)+1);
  1654. pValues->SetPropertyCString("playto", pPlayToBuffer);
  1655. if(pPlayToAssoc->m_regionName.GetLength() > 0)
  1656. {
  1657.     const char* pName = pPlayToAssoc->m_regionName;
  1658.     pRegionName->Set((BYTE*)pName, strlen(pName)+1);
  1659.     pValues->SetPropertyCString("region", pRegionName);
  1660. }
  1661.     }
  1662.     HX_RELEASE(pPlayToBuffer);
  1663.     HX_RELEASE(pRegionName);
  1664.     if (pStream &&
  1665. HXR_OK == pStream->QueryInterface(IID_IHXLayoutStream, (void**)&pLayoutStream))
  1666.     {
  1667. pLayoutStream->SetProperties(pValues);
  1668.     }
  1669.     HX_RELEASE(pLayoutStream);
  1670.     if(!pRegion->m_bImplicitRegion)
  1671.     {
  1672. addSiteForRenderer(pPlayToAssoc, pSourceInfo, pRenderer, FALSE);
  1673.     
  1674. if (!pStream)
  1675. {
  1676.     m_pParent->HandleAttachElementLayout((IUnknown*)pRenderer, pValues);
  1677. }
  1678.     }
  1679.     HX_RELEASE(pValues);
  1680.     // /XXXEH- end of "To do: the code inside this...".
  1681.     // /^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  1682.     return rc;
  1683. }
  1684. HX_RESULT
  1685. CSmilDocumentRenderer::DetachElementLayout(IUnknown* pLSG)
  1686. {
  1687.     HX_RESULT rc = HXR_OK;
  1688.     return rc;
  1689. }
  1690. BOOL CSmilDocumentRenderer::isRegionActive(const char* pszRegID, UINT16 usGroup, UINT32 ulTime)
  1691. {
  1692.     BOOL bRet = FALSE;
  1693.     if(m_pPlayToAssocList && pszRegID)
  1694.     {
  1695.         LISTPOSITION pos = m_pPlayToAssocList->GetHeadPosition();
  1696.         while (pos)
  1697.         {
  1698.             SMILPlayToAssoc* pAssoc =
  1699.                 (SMILPlayToAssoc*) m_pPlayToAssocList->GetNext(pos);
  1700.             if (pAssoc &&
  1701.                 pAssoc->m_uGroupIndex == usGroup &&
  1702.                 pAssoc->m_playTo      == pszRegID &&
  1703.                 ulTime                >= pAssoc->m_ulDelay &&
  1704.                 ulTime                <  pAssoc->m_ulDelay + pAssoc->m_ulDuration)
  1705.             {
  1706.                 bRet = TRUE;
  1707.                 break;
  1708.             }
  1709.         }
  1710.     }
  1711.     return bRet;
  1712. }
  1713. #if defined(BE_SITE_SUPPLIER_20010205)
  1714. // IHXSiteSupplier Interface Methods
  1715. /****************************************************************************
  1716.  *  IHXSiteSupplier::SitesNeeded                              ref:  hxwin.h
  1717.  *
  1718.  */
  1719. STDMETHODIMP
  1720. CSmilDocumentRenderer::SitesNeeded(UINT32 uRequestID, IHXValues* pProps)
  1721.     HX_RESULT pnrslt = HXR_OK; 
  1722.     HX_ASSERT(pProps); 
  1723.     if (!pProps) 
  1724.     { 
  1725. pnrslt = HXR_INVALID_PARAMETER; 
  1726.     } 
  1727.     else 
  1728.     { 
  1729. IHXSite* pChildSite = NULL;
  1730. SMILPlayToAssoc* pPlayToAssoc = NULL;
  1731. BOOL bNoRegion = TRUE;
  1732. // See if we need to layout this renderer
  1733. // First check to see if we have a region by id
  1734. CSmilBasicRegion* pRegion =
  1735. getRegionByID((const char*)m_XXXEH_HACK_regionId);
  1736. if(pRegion)
  1737. {
  1738.     bNoRegion = FALSE;
  1739. }
  1740. else
  1741. {
  1742.     // We didn't find it by id, so try finding a region by regionName:
  1743.     pRegion = getFirstRegionByName(m_XXXEH_HACK_regionId);
  1744.     if (pRegion)
  1745.     {
  1746. bNoRegion = FALSE;
  1747.     }
  1748.     else
  1749.     {
  1750. // Create a CSmilBasicRegion
  1751. pRegion = new CSmilBasicRegion(NULL);
  1752. if (pRegion)
  1753. {
  1754.     // Set the playto
  1755.     pRegion->m_region = m_XXXEH_HACK_regionId;
  1756.     // Set this as an implicit region
  1757.     pRegion->m_bImplicitRegion = TRUE;
  1758.     // Set width and height as unspecified
  1759.     pRegion->m_bWidthUnspecified  = TRUE;
  1760.     pRegion->m_bHeightUnspecified = TRUE;
  1761.     // Add it to the map
  1762.     (*m_pRegionMap)[m_XXXEH_HACK_regionId] = pRegion;
  1763. }
  1764.     }
  1765. }
  1766. pPlayToAssoc = pRegion? getPlayToAssoc(pRegion->m_region) : NULL;
  1767. HX_ASSERT(pPlayToAssoc);
  1768. if (!pPlayToAssoc)
  1769. {
  1770.     pnrslt = HXR_UNEXPECTED;
  1771. }
  1772. else
  1773. {
  1774.     const char* pPlayTo = pPlayToAssoc->m_playTo;
  1775.     IHXSite* pSite = pRegion->m_pSite;
  1776.     // Create a child site within the region:
  1777.     pSite->CreateChild(pChildSite);
  1778.             // Put this site into this region's list
  1779.             // of child renderer sites
  1780.             pRegion->addRendererSiteChild(pChildSite);
  1781.     // /Create a site watcher for this site
  1782.     CSmilSiteWatcher* pSiteWatch = new CSmilSiteWatcher(this,
  1783.     pRegion->m_region, TRUE /* <==is a child site */,
  1784.     pPlayToAssoc->m_id);
  1785.     if (pSiteWatch)
  1786.     {
  1787. // AddRef the watcher
  1788. pSiteWatch->AddRef();
  1789. // Get the top-level box
  1790. CSmilBasicBox* pTopBox = getTopLevelBox(pRegion);
  1791. if (pTopBox  &&  pTopBox->m_eResizeBehavior == ResizeZoom  &&
  1792. !m_bDoNotZoom)
  1793. {
  1794.     // Initialize the watcher with the current zoom factor;
  1795.     // is important if the player starts up in some zoom mode
  1796.     // other than original size.
  1797.     pSiteWatch->SetZoomScaleFactors(pRegion->m_dZoomScaleFactorX,
  1798. pRegion->m_dZoomScaleFactorY);
  1799. }
  1800. // Attach the watcher to the renderer site
  1801. HX_RESULT attchWatchRetVal = pChildSite->AttachWatcher(pSiteWatch);
  1802. if (SUCCEEDED(attchWatchRetVal))
  1803. {
  1804.     // Create the site watcher map if necessary
  1805.     if (!m_pSiteWatcherMap)
  1806.     {
  1807. m_pSiteWatcherMap = new CHXMapPtrToPtr();
  1808.     }
  1809.     if (m_pSiteWatcherMap)
  1810.     {
  1811. // Add the site watcher to the site watcher map
  1812. m_pSiteWatcherMap->SetAt((void*) pChildSite,
  1813.  (void*) pSiteWatch);
  1814.     }
  1815. }
  1816.     }
  1817.     HXxSize cCurSize;
  1818.     pSite->GetSize(cCurSize);
  1819.     cCurSize.cx-=40;
  1820.     cCurSize.cy-=40;
  1821.     pChildSite->SetSize(cCurSize);
  1822.     IHXSite2*  pSite2 = NULL;
  1823.     if (pChildSite  &&  pChildSite->QueryInterface(IID_IHXSite2,
  1824.     (void**)&pSite2) == HXR_OK)
  1825.     {
  1826. pSite2->ShowSite(TRUE);
  1827. pSite2->Release();
  1828.     }
  1829.     HRESULT     hresTemp = HXR_OK;
  1830.     IHXValues*     pSiteProps = NULL;
  1831.     IHXBuffer*     pValue = NULL;
  1832.     UINT32     style = 0;
  1833.     HX_VERIFY(HXR_OK == pChildSite->QueryInterface(IID_IHXValues,(void**)&pSiteProps));
  1834.     HX_ASSERT(pSiteProps);
  1835.     CSmilElement* pElement =
  1836.     m_pSmilParser->findElement(pPlayToAssoc->m_id);
  1837.     HX_ASSERT(pElement);
  1838.     // /Set the "sensitivity" (to mouse events) of the renderer site:
  1839.     if (pPlayToAssoc->m_id.GetLength() > 0  && m_pSmilParser)
  1840.     {
  1841. ULONG32 ulSensitivityStrLen = 0;
  1842. if (pElement &&
  1843. pElement->m_sensitivityToMouseEvents.GetLength() > 0)
  1844. {
  1845.     setSiteProperty(pChildSite, "sensitivity",
  1846.     (const char*)pElement->m_sensitivityToMouseEvents);
  1847. }
  1848.     }
  1849.     hresTemp = pProps->GetPropertyCString("playto",pValue);
  1850.     if (HXR_OK == hresTemp)
  1851.     {
  1852. pSiteProps->SetPropertyCString("channel",pValue);
  1853. pValue->Release();
  1854.     }
  1855.     else
  1856.     {
  1857. hresTemp = pProps->GetPropertyCString("name",pValue);
  1858. if (HXR_OK == hresTemp)
  1859. {
  1860.     pSiteProps->SetPropertyCString("LayoutGroup",pValue);
  1861.     pValue->Release();
  1862. }
  1863.     }
  1864.     pSiteProps->Release();
  1865.     // /Use child player site mgr.  It works; don't ask:
  1866.     IHXSiteManager* pSiteMgrOfIndependentPlayer = NULL;
  1867.     if (m_pIndependentPlayer  &&
  1868.     HXR_OK == m_pIndependentPlayer->
  1869.     QueryInterface(IID_IHXSiteManager,
  1870.     (void**)&pSiteMgrOfIndependentPlayer))
  1871.     {
  1872. // /Properties are set so now it's OK to add the site:
  1873. pSiteMgrOfIndependentPlayer->AddSite(pChildSite);
  1874. if (!m_pChildSiteInfoMap)
  1875. {
  1876.     m_pChildSiteInfoMap = new CHXMapLongToObj;
  1877. }
  1878. if (m_pChildSiteInfoMap)
  1879. {
  1880.     pChildSite->AddRef();
  1881.     pSite->AddRef();
  1882.     pSiteMgrOfIndependentPlayer->AddRef();
  1883.     SMILChildSiteInfo* pChildSiteInfo = new SMILChildSiteInfo(
  1884.     pChildSite, pSite, pSiteMgrOfIndependentPlayer);
  1885.     m_pChildSiteInfoMap->SetAt(uRequestID, pChildSiteInfo);
  1886. }
  1887.     }
  1888. }
  1889.     }
  1890.     return pnrslt;
  1891. }
  1892. /****************************************************************************
  1893.  *  IHXSiteSupplier::SitesNotNeeded                           ref:  hxwin.h
  1894.  *
  1895.  */
  1896. STDMETHODIMP 
  1897. CSmilDocumentRenderer::SitesNotNeeded(UINT32 uRequestID)
  1898. {
  1899.     SMILChildSiteInfo* pChildSiteInfo = NULL;
  1900.     // Locate the site
  1901.     if (!m_pChildSiteInfoMap  ||
  1902.     !m_pChildSiteInfoMap->Lookup(uRequestID, (void*& )pChildSiteInfo)  ||
  1903.     !pChildSiteInfo  ||  !pChildSiteInfo->m_pChildSite)
  1904.     {
  1905. HX_ASSERT(m_pChildSiteInfoMap  &&  pChildSiteInfo);
  1906. HX_ASSERT(pChildSiteInfo->m_pChildSite);
  1907. return HXR_INVALID_PARAMETER;
  1908.     }
  1909.     if (m_pSiteWatcherMap)
  1910.     {
  1911.         void* pVoid = NULL;
  1912.         if (m_pSiteWatcherMap->Lookup((void*)pChildSiteInfo->m_pChildSite, pVoid)  &&  pVoid)
  1913.         {
  1914.             // Get the CSmilSiteWatcher pointer
  1915.             CSmilSiteWatcher* pWatcher = (CSmilSiteWatcher*)pVoid;
  1916.             // Remove the site watcher from the site watcher map
  1917.             m_pSiteWatcherMap->RemoveKey((void*)pChildSiteInfo->m_pChildSite);
  1918.             // Release our ref on the site watcher
  1919.             HX_RELEASE(pWatcher);
  1920.         }
  1921.     }
  1922.     HX_ASSERT(pChildSiteInfo->m_pSiteMgr);
  1923.     HX_ASSERT(pChildSiteInfo->m_pParentSite);
  1924.     // Perform cleanup on child site
  1925.     pChildSiteInfo->m_pChildSite->DetachWatcher();
  1926.     pChildSiteInfo->m_pSiteMgr->RemoveSite(pChildSiteInfo->m_pChildSite);
  1927.     pChildSiteInfo->m_pParentSite->DestroyChild(pChildSiteInfo->m_pChildSite);
  1928.     pChildSiteInfo->m_pChildSite->Release();
  1929.     // Remove from map and free memory
  1930.     m_pChildSiteInfoMap->RemoveKey(uRequestID);
  1931.     delete pChildSiteInfo;
  1932.     return HXR_OK;
  1933. }
  1934. /****************************************************************************
  1935.  *  IHXSiteSupplier::BeginChangeLayout                        ref:  hxwin.h
  1936.  *
  1937.  */
  1938. STDMETHODIMP 
  1939. CSmilDocumentRenderer::BeginChangeLayout()
  1940. {
  1941.     return HXR_OK;
  1942. }
  1943. /****************************************************************************
  1944.  *  IHXSiteSupplier::DoneChangeLayout                         ref:  hxwin.h
  1945.  *
  1946.  */
  1947. STDMETHODIMP 
  1948. CSmilDocumentRenderer::DoneChangeLayout()
  1949. {
  1950.     return HXR_OK;
  1951. }
  1952. #endif /* BE_SITE_SUPPLIER_20010205 */
  1953. STDMETHODIMP CSmilDocumentRenderer::MarkerResolved(IHXBuffer* pURLStr,
  1954.                                                    IHXBuffer* pMarkerNameStr,
  1955.                                                    UINT32      ulTime,
  1956.                                                    IHXValues* pOtherMarkerParams)
  1957. {
  1958.     HX_RESULT retVal = HXR_OK;
  1959.     // Now we need to run through the playToAssoc list
  1960.     // and find any id's which correspond to this URL
  1961.     if (pURLStr && pMarkerNameStr && m_pPlayToAssocList)
  1962.     {
  1963.         LISTPOSITION pos = m_pPlayToAssocList->GetHeadPosition();
  1964.         while (pos)
  1965.         {
  1966.             SMILPlayToAssoc* pAssoc =
  1967.                 (SMILPlayToAssoc*) m_pPlayToAssocList->GetNext(pos);
  1968.             if (pAssoc &&
  1969.                 !strcmp((const char*) pURLStr->GetBuffer(),
  1970.                         (const char*) pAssoc->m_URL))
  1971.             {
  1972.                 // Init a temp list
  1973.                 CHXSimpleList cTmp;
  1974.                 // First check and see if this URL comes from
  1975.                 // an external media marker file.
  1976.                 CExternalMediaMarkerInfo* pInfo = getExternalMediaMarkerInfo(pAssoc->m_URL);
  1977.                 if (pInfo && pInfo->m_pIDList)
  1978.                 {
  1979.                     LISTPOSITION pos = pInfo->m_pIDList->GetHeadPosition();
  1980.                     while (pos)
  1981.                     {
  1982.                         const char* pszID = (const char*) pInfo->m_pIDList->GetNext(pos);
  1983.                         if (pszID)
  1984.                         {
  1985.                             cTmp.AddTail((void*) pszID);
  1986.                         }
  1987.                     }
  1988.                 }
  1989.                 else
  1990.                 {
  1991.                     cTmp.AddTail((void*) (const char*) pAssoc->m_id);
  1992.                 }
  1993.                 // Now run through our temporary list and 
  1994.                 // resolve this marker to all id's.
  1995.                 BOOL         bDoHandle = FALSE;
  1996.                 LISTPOSITION tpos      = cTmp.GetHeadPosition();
  1997.                 while (tpos && SUCCEEDED(retVal))
  1998.                 {
  1999.                     const char* pszID = (const char*) cTmp.GetNext(tpos);
  2000.                     if (pszID)
  2001.                     {
  2002.                         BOOL bHandle = FALSE;
  2003.                         retVal = m_pSmilParser->resolveMediaMarkerTime(pszID,
  2004.                                                                        (const char*) pMarkerNameStr->GetBuffer(),
  2005.                                                                        ulTime,
  2006.                                                                        bHandle);
  2007.                         if (SUCCEEDED(retVal) && bHandle)
  2008.                         {
  2009.                             bDoHandle = TRUE;
  2010.                         }
  2011.                     }
  2012.                 }
  2013.                 if (SUCCEEDED(retVal) && bDoHandle)
  2014.                 {
  2015.                     handleElements();
  2016.                 }
  2017.             }
  2018.         }
  2019.     }
  2020.     return retVal;
  2021. }
  2022. STDMETHODIMP CSmilDocumentRenderer::EventFired(IHXBuffer* pURLStr,
  2023.                                                IHXBuffer* pFragmentStr,
  2024.                                                IHXBuffer* pEventNameStr,
  2025.                                                IHXValues* pOtherValues)
  2026. {
  2027.     HX_RESULT retVal = HXR_OK;
  2028.     if (pURLStr && pEventNameStr)
  2029.     {
  2030.         LISTPOSITION pos = m_pPlayToAssocList->GetHeadPosition();
  2031.         while (pos)
  2032.         {
  2033.             SMILPlayToAssoc* pAssoc =
  2034.                 (SMILPlayToAssoc*) m_pPlayToAssocList->GetNext(pos);
  2035.             if (pAssoc &&
  2036.                 !strcmp((const char*) pAssoc->m_URL,
  2037.                         (const char*) pURLStr->GetBuffer()))
  2038.             {
  2039.                 retVal = handleNamedEvent((const char*) pAssoc->m_playTo,
  2040.                                           (const char*) pAssoc->m_id, 
  2041.                                           (const char*) pEventNameStr->GetBuffer());
  2042.             }
  2043.         }
  2044.     }
  2045.     else
  2046.     {
  2047.         retVal = HXR_FAIL;
  2048.     }
  2049.     return retVal;
  2050. }
  2051. STDMETHODIMP CSmilDocumentRenderer::ErrorOccurred(const UINT8   unSeverity,
  2052.                                                   const ULONG32 ulHXCode,
  2053.                                                   const ULONG32 ulUserCode,
  2054.                                                   const char*   pUserString,
  2055.                                                   const char*   pMoreInfoURL)
  2056. {
  2057.     HX_RESULT retVal = HXR_OK;
  2058.     MLOG_FLOW(m_pErrorMessages, "ErrorOccurred(%u,%lu,%lu,%s,%s)n",
  2059.               unSeverity, ulHXCode, ulUserCode, pUserString, pMoreInfoURL);
  2060.     return retVal;
  2061. }
  2062. HX_RESULT
  2063. CSmilDocumentRenderer::InitPersistent(UINT32 ulPersistentComponentID,
  2064.       UINT16 uPersistentGroupID,
  2065.       UINT16 uPersistentTrackID,
  2066.       IHXPersistentRenderer* pPersistentParent)
  2067. {
  2068.     IHXStreamSource* pPersistentSource = NULL;
  2069.     IHXStream* pPersistentStream = NULL;
  2070.     m_ulPersistentComponentID = ulPersistentComponentID;
  2071.     m_uPersistentGroupID = uPersistentGroupID;
  2072.     m_uPersistentTrackID = uPersistentTrackID;
  2073.     m_pPersistentParentRenderer = pPersistentParent;
  2074.     HX_ADDREF(m_pPersistentParentRenderer);
  2075.     if (m_pContext &&
  2076. HXR_OK == m_pContext->QueryInterface(IID_IHXStreamSource, (void**)&pPersistentSource))
  2077.     {
  2078. if (HXR_OK == pPersistentSource->GetStream(0, (IUnknown*&)pPersistentStream))
  2079. {
  2080.          if (HXR_OK != pPersistentStream->QueryInterface(IID_IHXLayoutStream, (void**)&m_pPersistentLayoutStream))
  2081.     {   
  2082. HX_ASSERT(m_pPersistentLayoutStream);
  2083.     }
  2084. }
  2085. HX_RELEASE(pPersistentStream);
  2086.     }
  2087.     HX_RELEASE(pPersistentSource);
  2088.     
  2089.     return HXR_OK;
  2090. }
  2091. BOOL
  2092. CSmilDocumentRenderer::IsNestedMetaSupported(void)
  2093. {
  2094.     BOOL     bResult = TRUE;    
  2095.     UINT32     ulParentPersistentVersion = 0;
  2096.     UINT32     ulParentPersistentMajorVersion = 0;
  2097.     UINT32     ulParentPersistentType = PersistentUnknown;
  2098.     IHXValues*     pProperties = NULL;
  2099.     if (!m_pPersistentParentRenderer)
  2100.     {
  2101. return bResult;
  2102.     }
  2103.     if (HXR_OK == m_pPersistentParentRenderer->GetPersistentProperties(pProperties))
  2104.     {
  2105. pProperties->GetPropertyULONG32("PersistentType", ulParentPersistentType);
  2106. pProperties->GetPropertyULONG32("PersistentVersion", ulParentPersistentVersion);
  2107. ulParentPersistentMajorVersion = HX_GET_MAJOR_VERSION(ulParentPersistentVersion);
  2108. switch (ulParentPersistentType)
  2109. {
  2110. case PersistentUnknown:
  2111.     bResult = FALSE;
  2112.     break;
  2113. case PersistentSMIL:
  2114.     if (ulParentPersistentMajorVersion == 1)
  2115.     {
  2116. bResult = FALSE;
  2117.     }
  2118.     break;
  2119. default:
  2120.     break;
  2121. }
  2122.     }
  2123.     HX_RELEASE(pProperties);
  2124.     
  2125.     return bResult;
  2126. }
  2127. void
  2128. CSmilDocumentRenderer::PersistentDurationSet(UINT32 ulDuration, 
  2129.      UINT32 ulDelay, 
  2130.      BOOL bIsLive)
  2131. {
  2132.     IHXRendererAdviseSink* pRendererAdviseSink = NULL;
  2133.     if (m_pPersistentParentRenderer &&
  2134. HXR_OK == m_pPersistentParentRenderer->QueryInterface(IID_IHXRendererAdviseSink, (void**)&pRendererAdviseSink))
  2135.     {
  2136. pRendererAdviseSink->TrackDurationSet(m_uPersistentGroupID,
  2137.       m_uPersistentTrackID,
  2138.       ulDuration,
  2139.       ulDelay,
  2140.       bIsLive);
  2141.     }
  2142.     HX_RELEASE(pRendererAdviseSink);
  2143.     return;
  2144. }
  2145. FillType CSmilDocumentRenderer::getMediaFillBehavior(const char* pszID)
  2146. {
  2147.     FillType eRet = FillDefault;
  2148.     if (pszID && m_pSmilParser)
  2149.     {
  2150.         CSmilElement* pElement = m_pSmilParser->findElement(pszID);
  2151.         if (pElement)
  2152.         {
  2153.             eRet = pElement->m_eActualFill;
  2154.         }
  2155.     }
  2156.     return eRet;
  2157. }
  2158. BOOL CSmilDocumentRenderer::atLeastOneActiveAnimation(UINT32 ulTime)
  2159. {
  2160.     BOOL bRet = FALSE;
  2161. #if defined(HELIX_FEATURE_SMIL2_ANIMATION)
  2162.     if (m_pActiveAnimations &&
  2163.         m_pActiveAnimations->GetCount() > 0)
  2164.     {
  2165.         // Run through all active animations and check
  2166.         LISTPOSITION pos = m_pActiveAnimations->GetHeadPosition();
  2167.         while (pos)
  2168.         {
  2169.             CSmilAnimateInfo* pInfo =
  2170.                 (CSmilAnimateInfo*) m_pActiveAnimations->GetNext(pos);
  2171.             if (pInfo &&
  2172.                 pInfo->m_pSandwich &&
  2173.                 pInfo->m_pSandwich->GetAttributeName() != kAttrNameSoundLevel &&
  2174.                 pInfo->m_pSandwich->AtLeastOneActiveLayer(ulTime))
  2175.             {
  2176.                 bRet = TRUE;
  2177.                 break;
  2178.             }
  2179.         }
  2180.     }
  2181. #endif /* #if defined(HELIX_FEATURE_SMIL2_ANIMATION) */
  2182.     return bRet;
  2183. }
  2184. void CSmilDocumentRenderer::clearAllEventHandledFlags()
  2185. {
  2186.     if(m_pEventList && m_pEventList->GetCount() > 0)
  2187.     {
  2188.         LISTPOSITION pos = m_pEventList->GetHeadPosition();
  2189.         while(pos)
  2190.         {
  2191.             CSmilLayoutEvent* pEvent =
  2192.                 (CSmilLayoutEvent*) m_pEventList->GetNext(pos);
  2193.             if (pEvent)
  2194.             {
  2195.                 pEvent->setHandledFlag(FALSE);
  2196.             }
  2197.         }
  2198.     }
  2199. }
  2200. HX_RESULT CSmilDocumentRenderer::setRendererULONG32Property(const char* pszMediaID,
  2201.                                                             const char* pszName,
  2202.                                                             UINT32      ulValue,
  2203.                                                             REF(BOOL)   rbSetNewValue)
  2204. {
  2205.     HX_RESULT retVal = HXR_FAIL;
  2206.     if (pszMediaID && pszName)
  2207.     {
  2208.         // Set the default
  2209.         rbSetNewValue = FALSE;
  2210.         // Get the IHXRenderer
  2211.         IHXRenderer* pRenderer = NULL;
  2212.         retVal = getRenderer(pszMediaID, pRenderer);
  2213.         if (SUCCEEDED(retVal))
  2214.         {
  2215.             // QI IHXRenderer for IHXValues
  2216.             IHXValues* pValues = NULL;
  2217.             retVal = pRenderer->QueryInterface(IID_IHXValues, (void**) &pValues);
  2218.             if (SUCCEEDED(retVal))
  2219.             {
  2220.                 // Get the current value. If we can't get the value,
  2221.                 // that's OK, since we are only using this current
  2222.                 // value to optimize out any unnecessary setting
  2223.                 // of properties
  2224.                 UINT32 ulCurValue = 0;
  2225.                 HX_RESULT rv = pValues->GetPropertyULONG32(pszName, ulCurValue);
  2226.                 // Is the current value different from the 
  2227.                 // value we're trying to set?
  2228.                 if ((SUCCEEDED(rv) && ulCurValue != ulValue) || FAILED(rv))
  2229.                 {
  2230.                     retVal = pValues->SetPropertyULONG32(pszName, ulValue);
  2231.                     if (SUCCEEDED(retVal))
  2232.                     {
  2233.                         rbSetNewValue = TRUE;
  2234.                     }
  2235.                 }
  2236.             }
  2237.             HX_RELEASE(pValues);
  2238.         }
  2239.         HX_RELEASE(pRenderer);
  2240.     }
  2241.     return retVal;
  2242. }
  2243. HX_RESULT CSmilDocumentRenderer::setRendererCStringProperty(const char* pszMediaID,
  2244.                                                             const char* pszName,
  2245.                                                             const char* pszValue,
  2246.                                                             REF(BOOL)   rbSetNewValue)
  2247. {
  2248.     HX_RESULT retVal = HXR_FAIL;
  2249.     if (pszMediaID && pszName && pszValue)
  2250.     {
  2251.         // Set the default
  2252.         rbSetNewValue = FALSE;
  2253.         // Get the IHXRenderer
  2254.         IHXRenderer* pRenderer = NULL;
  2255.         retVal = getRenderer(pszMediaID, pRenderer);
  2256.         if (SUCCEEDED(retVal))
  2257.         {
  2258.             // QI IHXRenderer for IHXValues
  2259.             IHXValues* pValues = NULL;
  2260.             retVal = pRenderer->QueryInterface(IID_IHXValues, (void**) &pValues);
  2261.             if (SUCCEEDED(retVal))
  2262.             {
  2263.                 // Get the current value. If we can't get the value,
  2264.                 // that's OK, since we are only using this current
  2265.                 // value to optimize out any unnecessary setting
  2266.                 // of properties
  2267.                 BOOL        bSame     = FALSE;
  2268.                 IHXBuffer* pCurValue = NULL;
  2269.                 HX_RESULT rv = pValues->GetPropertyCString(pszName, pCurValue);
  2270.                 if (SUCCEEDED(rv))
  2271.                 {
  2272.                     const char* pszCurValue = (const char*) pCurValue->GetBuffer();
  2273.                     if (pszCurValue)
  2274.                     {
  2275.                         if (!strcmp(pszCurValue, pszValue))
  2276.                         {
  2277.                             bSame = TRUE;
  2278.                         }
  2279.                     }
  2280.                 }
  2281.                 // Release the current value buffer
  2282.                 HX_RELEASE(pCurValue);
  2283.                 // Is the current value different from the 
  2284.                 // value we're trying to set?
  2285.                 if ((SUCCEEDED(rv) && !bSame) || FAILED(rv))
  2286.                 {
  2287.                     // Set the flag
  2288.                     rbSetNewValue = TRUE;
  2289.                     // Set the CString property
  2290.                     setProperty(pValues, pszName, pszValue);
  2291.                 }
  2292.             }
  2293.             HX_RELEASE(pValues);
  2294.         }
  2295.         HX_RELEASE(pRenderer);
  2296.     }
  2297.     return retVal;
  2298. }
  2299. void CSmilDocumentRenderer::addRemoveMediaMarkerSink(BOOL bAdd)
  2300. {
  2301.     if (m_pContext)
  2302.     {
  2303.         // QI for IHXMediaMarkerManager
  2304.         IHXMediaMarkerManager* pMediaMarkerManager = NULL;
  2305.         m_pContext->QueryInterface(IID_IHXMediaMarkerManager,
  2306.                                    (void**) &pMediaMarkerManager);
  2307.         if (pMediaMarkerManager)
  2308.         {
  2309.             // Get our own IHXMediaMarkerSink interface
  2310.             IHXMediaMarkerSink* pSink = NULL;
  2311.             QueryInterface(IID_IHXMediaMarkerSink, (void**) &pSink);
  2312.             if (pSink)
  2313.             {
  2314.                 if (bAdd)
  2315.                 {
  2316.                     // Add ourselves as a sink
  2317.                     pMediaMarkerManager->AddMediaMarkerSink(pSink);
  2318.                 }
  2319.                 else
  2320.                 {
  2321.                     // Remove ourselves as a sink
  2322.                     pMediaMarkerManager->RemoveMediaMarkerSink(pSink);
  2323.                 }
  2324.             }
  2325.             HX_RELEASE(pSink);
  2326.         }
  2327.         HX_RELEASE(pMediaMarkerManager);
  2328.     }
  2329. }
  2330. void CSmilDocumentRenderer::addRemoveEventSink(BOOL bAdd)
  2331. {
  2332.     if (m_pContext)
  2333.     {
  2334.         // QI for IHXEventManager
  2335.         IHXEventManager* pEventManager = NULL;
  2336.         m_pContext->QueryInterface(IID_IHXEventManager,
  2337.                                    (void**) &pEventManager);
  2338.         if (pEventManager)
  2339.         {
  2340.             // Get our own IHXEventSink interface
  2341.             IHXEventSink* pSink = NULL;
  2342.             QueryInterface(IID_IHXEventSink, (void**) &pSink);
  2343.             if (pSink)
  2344.             {
  2345.                 if (bAdd)
  2346.                 {
  2347.                     // Add ourselves as a sink
  2348.                     pEventManager->AddEventSink(pSink);
  2349.                     // Set the flag
  2350.                     m_bEventSinkWasSetup = TRUE;
  2351.                 }
  2352.                 else
  2353.                 {
  2354.                     // Remove ourselves as a sink
  2355.                     pEventManager->RemoveEventSink(pSink);
  2356.                     // Clera the flag
  2357.                     m_bEventSinkWasSetup = FALSE;
  2358.                 }
  2359.             }
  2360.             HX_RELEASE(pSink);
  2361.         }
  2362.         HX_RELEASE(pEventManager);
  2363.     }
  2364. }
  2365. void CSmilDocumentRenderer::addRemoveErrorSink(BOOL bAdd)
  2366. {
  2367.     if (m_pContext)
  2368.     {
  2369.         // QI for IHXErrorSinkControl
  2370.         IHXErrorSinkControl* pErrorSinkControl = NULL;
  2371.         m_pContext->QueryInterface(IID_IHXErrorSinkControl,
  2372.                                    (void**) &pErrorSinkControl);
  2373.         if (pErrorSinkControl)
  2374.         {
  2375.             // Get our own IHXEventSink interface
  2376.             IHXErrorSink* pSink = NULL;
  2377.             QueryInterface(IID_IHXErrorSink, (void**) &pSink);
  2378.             if (pSink)
  2379.             {
  2380.                 if (bAdd)
  2381.                 {
  2382.                     // Add ourselves as a sink
  2383.                     pErrorSinkControl->AddErrorSink(pSink,
  2384.                                                     HXLOG_EMERG,
  2385.                                                     HXLOG_DEBUG);
  2386.                 }
  2387.                 else
  2388.                 {
  2389.                     // Remove ourselves as a sink
  2390.                     pErrorSinkControl->RemoveErrorSink(pSink);
  2391.                 }
  2392.             }
  2393.             HX_RELEASE(pSink);
  2394.         }
  2395.         HX_RELEASE(pErrorSinkControl);
  2396.     }
  2397. }
  2398. void CSmilDocumentRenderer::addEventSinkFilterRule(const char*    pszURL,
  2399.                                                    const char*    pszFragment,
  2400.                                                    const char*    pszEventName,
  2401.                                                    IHXEventSink* pSink)
  2402. {
  2403.     if (m_pContext && m_pParent &&
  2404.         (pszURL || pszFragment || pszEventName))
  2405.     {
  2406.         // QI for IHXEventManager
  2407.         IHXEventManager* pEventManager = NULL;
  2408.         m_pContext->QueryInterface(IID_IHXEventManager,
  2409.                                    (void**) &pEventManager);
  2410.         if (pEventManager)
  2411.         {
  2412.             // If we have a sink passed in, use it. If
  2413.             // not, then get our own event sink interface
  2414.             BOOL bOurSink = FALSE;
  2415.             if (!pSink)
  2416.             {
  2417.                 // Set the flag so that we'll know this is 
  2418.                 // our interface (and we need to release it
  2419.                 // at the bottom of this method)
  2420.                 bOurSink = TRUE;
  2421.                 // Get our own IHXEventSink interface
  2422.                 QueryInterface(IID_IHXEventSink, (void**) &pSink);
  2423.             }
  2424.             if (pSink)
  2425.             {
  2426.                 // Create an IHXValues
  2427.                 IHXCommonClassFactory* pFact = m_pParent->getFactory();
  2428.                 if (pFact)
  2429.                 {
  2430.                     IHXValues* pRule = NULL;
  2431.                     pFact->CreateInstance(CLSID_IHXValues, (void**) &pRule);
  2432.                     if (pRule)
  2433.                     {
  2434.                         // Set URL string
  2435.                         if (pszURL)
  2436.                         {
  2437.                             setProperty(pRule, FILTER_RULE_KEY_URL,
  2438.                                         pszURL);
  2439.                         }
  2440.                         // Set fragment string
  2441.                         if (pszFragment)
  2442.                         {
  2443.                             setProperty(pRule, FILTER_RULE_KEY_FRAGMENT,
  2444.                                         pszFragment);
  2445.                         }
  2446.                         // Set eventName string
  2447.                         if (pszEventName)
  2448.                         {
  2449.                             setProperty(pRule, FILTER_RULE_KEY_EVENTNAME,
  2450.                                         pszEventName);
  2451.                         }
  2452.                         // Add the rule
  2453.                         pEventManager->AddEventSinkFilterRule(pSink, pRule);
  2454.                     }
  2455.                     HX_RELEASE(pRule);
  2456.                 }
  2457.             }
  2458.             // If this was our sink interface, then
  2459.             // we need to release it
  2460.             if (bOurSink)
  2461.             {
  2462.                 HX_RELEASE(pSink);
  2463.             }
  2464.         }
  2465.         HX_RELEASE(pEventManager);
  2466.     }
  2467. }
  2468. HX_RESULT CSmilDocumentRenderer::getEventSink(const char*         pszID,
  2469.                                               REF(IHXEventSink*) rpEventSink)
  2470. {
  2471.     HX_RESULT retVal = HXR_FAIL;
  2472.     if (pszID)
  2473.     {
  2474.         // Get the IHXRenderer interface
  2475.         IHXRenderer* pRenderer = NULL;
  2476.         retVal = getRenderer(pszID, pRenderer);
  2477.         if (SUCCEEDED(retVal))
  2478.         {
  2479.             // QI for IHXEventSink
  2480.             HX_RELEASE(rpEventSink);
  2481.             retVal = pRenderer->QueryInterface(IID_IHXEventSink,
  2482.                                                (void**) &rpEventSink);
  2483.         }
  2484.         HX_RELEASE(pRenderer);
  2485.     }
  2486.     return retVal;
  2487. }
  2488. HX_RESULT CSmilDocumentRenderer::addRemoveEventSink(const char* pszID,
  2489.                                                     BOOL        bAdd)
  2490. {
  2491.     HX_RESULT retVal = HXR_FAIL;
  2492.     if (pszID && m_pContext)
  2493.     {
  2494.         // See if we can get the IHXEventSink interface
  2495.         IHXEventSink* pSink = NULL;
  2496.         retVal = getEventSink(pszID, pSink);
  2497.         if (SUCCEEDED(retVal))
  2498.         {
  2499.             // Check if the event sink is already setup
  2500.             BOOL         bSinkIsSetup = FALSE;
  2501.             LISTPOSITION pos          = NULL;
  2502.             if (m_pEventSinkList)
  2503.             {
  2504.                 pos = m_pEventSinkList->GetHeadPosition();
  2505.                 while (pos)
  2506.                 {
  2507.                     IHXEventSink* pListSink =
  2508.                         (IHXEventSink*) m_pEventSinkList->GetAt(pos);
  2509.                     if (pListSink && pListSink == pSink)
  2510.                     {
  2511.                         bSinkIsSetup = TRUE;
  2512.                         break;
  2513.                     }
  2514.                     m_pEventSinkList->GetNext(pos);
  2515.                 }
  2516.             }
  2517.             // We only have work to do if:
  2518.             // a) we are adding and it's not already setup; OR
  2519.             // b) we are removing and it's already setup.
  2520.             if (( bAdd && !bSinkIsSetup) ||
  2521.                 (!bAdd &&  bSinkIsSetup))
  2522.             {
  2523.                 // Get the IHXEventManager interface
  2524.                 IHXEventManager* pMgr = NULL;
  2525.                 retVal = m_pContext->QueryInterface(IID_IHXEventManager,
  2526.                                                     (void**) &pMgr);
  2527.                 if (SUCCEEDED(retVal))
  2528.                 {
  2529.                     // Are we adding or removing?
  2530.                     if (bAdd)
  2531.                     {
  2532.                         // Add the event sink to the event manager
  2533.                         retVal = pMgr->AddEventSink(pSink);
  2534.                         if (SUCCEEDED(retVal))
  2535.                         {
  2536.                             // Do we have a event sink list yet?
  2537.                             if (!m_pEventSinkList)
  2538.                             {
  2539.                                 m_pEventSinkList = new CHXSimpleList();
  2540.                             }
  2541.                             if (m_pEventSinkList)
  2542.                             {
  2543.                                 // AddRef the event sink before it goes on the list
  2544.                                 pSink->AddRef();
  2545.                                 // Add it to the list
  2546.                                 m_pEventSinkList->AddTail((void*) pSink);
  2547.                             }
  2548.                             else
  2549.                             {
  2550.                                 retVal = HXR_FAIL;
  2551.                             }
  2552.                         }
  2553.                     }
  2554.                     else
  2555.                     {
  2556.                         // Remove the event sink from the event manager
  2557.                         retVal = pMgr->RemoveEventSink(pSink);
  2558.                         if (SUCCEEDED(retVal))
  2559.                         {
  2560.                             // Remove it from the list
  2561.                             m_pEventSinkList->RemoveAt(pos);
  2562.                             // Release the list's ref on the sink
  2563.                             pSink->Release();
  2564.                         }
  2565.                     }
  2566.                 }
  2567.                 HX_RELEASE(pMgr);
  2568.             }
  2569.         }
  2570.         HX_RELEASE(pSink);
  2571.     }
  2572.     return retVal;
  2573. }
  2574. void CSmilDocumentRenderer::removeAllEventSinks()
  2575. {
  2576.     if (m_pEventSinkList && m_pContext)
  2577.     {
  2578.         IHXEventManager* pMgr = NULL;
  2579.         m_pContext->QueryInterface(IID_IHXEventManager, (void**) &pMgr);
  2580.         if (pMgr)
  2581.         {
  2582.             LISTPOSITION pos = m_pEventSinkList->GetHeadPosition();
  2583.             while (pos)
  2584.             {
  2585.                 // Get the sink
  2586.                 IHXEventSink* pSink =
  2587.                     (IHXEventSink*) m_pEventSinkList->GetNext(pos);
  2588.                 // Remove the event sink from the event manager
  2589.                 pMgr->RemoveEventSink(pSink);
  2590.                 // Release the list's ref on the sink
  2591.                 HX_RELEASE(pSink);
  2592.             }
  2593.             // Remove all entries from the list
  2594.             m_pEventSinkList->RemoveAll();
  2595.         }
  2596.         HX_RELEASE(pMgr);
  2597.     }
  2598. }
  2599. HX_RESULT CSmilDocumentRenderer::setupEventPipe(const char* pszSrcID,
  2600.                                                 const char* pszDstID,
  2601.                                                 const char* pszEventName)
  2602. {
  2603.     HX_RESULT retVal = HXR_FAIL;
  2604.     if (pszSrcID && pszDstID)
  2605.     {
  2606.         // We have to setup the destination renderer as a event sink.
  2607.         // If it's not setup yet OR the renderer doesn't support
  2608.         // IHXEventSink, then this call will fail.
  2609.         retVal = addRemoveEventSink(pszDstID, TRUE);
  2610.         if (SUCCEEDED(retVal))
  2611.         {
  2612.             // First get the playToAssoc
  2613.             SMILPlayToAssoc* pAssoc = getPlayToAssocByMedia(pszSrcID);
  2614.             if (pAssoc)
  2615.             {
  2616.                 // Get the src media URL from the playToAssoc
  2617.                 const char* pszURL = (const char*) pAssoc->m_URL;
  2618.                 // Get the destination event sink
  2619.                 IHXEventSink* pSink = NULL;
  2620.                 retVal = getEventSink(pszDstID, pSink);
  2621.                 if (SUCCEEDED(retVal))
  2622.                 {
  2623.                     // Now we need to add a filter rule that will
  2624.                     // let this sink get events from the src media
  2625.                     addEventSinkFilterRule(pszURL, NULL, pszEventName, pSink);
  2626.                 }
  2627.                 HX_RELEASE(pSink);
  2628.             }
  2629.             else
  2630.             {
  2631.                 retVal = HXR_FAIL;
  2632.             }
  2633.         }
  2634.     }
  2635.     return retVal;
  2636. }
  2637. void
  2638. CSmilDocumentRenderer::handlePendingScheduling(void)
  2639. {
  2640.     // /We need to call handlePendingScheduling in case
  2641.     // this endEvent is from the last-active track in which
  2642.     // case the core will not give us any more time syncs
  2643.     // so we can't do the following in onTimeSync():
  2644.     BOOL bSomeElementScheduleWasChanged = FALSE;
  2645.     HX_RESULT tmprslt =
  2646.     m_pSmilParser->handlePendingScheduling(
  2647.     m_ulCurrentTime,
  2648.     m_uCurrentGroupIndex,
  2649.     bSomeElementScheduleWasChanged,
  2650.     // /We don't need to get list of paused elements:
  2651.     NULL, NULL);
  2652.     if (SUCCEEDED(tmprslt) && bSomeElementScheduleWasChanged)
  2653.     {
  2654. handleElements();
  2655.     }
  2656.     return;
  2657. }
  2658. HX_RESULT
  2659. CSmilDocumentRenderer::AdjustSoundLevelsOfAllCurrentTracks(
  2660. UINT16 uCurGroupIndex,
  2661. // /Adjust each track's sound level by this amount, so if current
  2662. // level of track is 50% and this adjustment_pct is 60%, then new
  2663. // sound level for that track would be 30% (= 60% of 50%):
  2664. UINT32 ulSoundLevelAdjustment_pct,
  2665. // /In case track is being restarted by link-region-target HURL, don't
  2666. // mess with its soundLevel as that will be set in handleSource():
  2667. CSmilSource* pSmilSourceDontAdjustMe)
  2668. {
  2669.     HX_RESULT pnrslt = HXR_OK;
  2670.     // /Get all currently-playing tracks and adjust their soundLevel values:
  2671.     if(m_pPlayToAssocList)
  2672.     {
  2673. CHXSimpleList::Iterator i = m_pPlayToAssocList->Begin();
  2674. for (; i!=m_pPlayToAssocList->End(); ++i)
  2675. {
  2676.     SMILPlayToAssoc* pPlayToAssoc = (SMILPlayToAssoc*)(*i);
  2677.     // /XXXEH- do this for already-played-and-stopped ones in this
  2678.     // group?  I think so, in case there's a seek backwards:
  2679.     if (pPlayToAssoc->m_uGroupIndex >= uCurGroupIndex)
  2680.     {
  2681. if (pSmilSourceDontAdjustMe  &&  pPlayToAssoc->m_id ==
  2682. pSmilSourceDontAdjustMe->m_pNode->m_id)
  2683. {
  2684.     continue;
  2685. }
  2686. IHXTrack* pTrack = NULL;
  2687. HX_RESULT rtvlgetTrack = getTrack(pPlayToAssoc->m_uGroupIndex,
  2688. pPlayToAssoc->m_uTrackIndex, pTrack);
  2689. if (SUCCEEDED(rtvlgetTrack))
  2690. {
  2691.     UINT16 usPriorSoundLevel_pct = pTrack->GetSoundLevel();
  2692.     UINT16 usNewSoundLevel_pct = (usPriorSoundLevel_pct *
  2693.     (UINT16)ulSoundLevelAdjustment_pct) / 100;
  2694.     if (usNewSoundLevel_pct > (UINT16)MAX_ALLOWED_SOUNDLEVEL)
  2695.     {
  2696. usNewSoundLevel_pct = (UINT16)MAX_ALLOWED_SOUNDLEVEL;
  2697.     }
  2698.     pTrack->SetSoundLevel(usNewSoundLevel_pct);
  2699. }
  2700. HX_RELEASE(pTrack);
  2701.     }
  2702. }
  2703.     }
  2704.     // /To handle all not-yet-added tracks, set this for adjusting their
  2705.     // soundLevel values in ::handleSource():
  2706. // /XXXEH- finish this!
  2707.  
  2708.     return pnrslt;
  2709. }
  2710. void CSmilDocumentRenderer::SendHyperlinkHints()
  2711. {
  2712.     if(m_pParent)
  2713.     {
  2714.         IHXPlayer* pPlayer = m_pParent->getPlayer();
  2715.         if(pPlayer && m_pSmilParser)
  2716.         {
  2717.             // Get the <smil> node
  2718.             SMILNode* pTopNode = m_pSmilParser->findFirstNode(SMILSmil);
  2719.             if (pTopNode)
  2720.             {
  2721.                 // Now recurse down the tree
  2722.                 HintHyperlinkNodeRecurse(pTopNode);
  2723.             }
  2724.         }
  2725.     }
  2726. }
  2727. void CSmilDocumentRenderer::HintHyperlinkNodeRecurse(SMILNode* pNode)
  2728. {
  2729.     if (pNode)
  2730.     {
  2731.         // Check if it's a hyperlinking node
  2732.         if (pNode->m_tag == SMILAAnchor ||
  2733.             pNode->m_tag == SMILArea    ||
  2734.             pNode->m_tag == SMILAnchor)
  2735.         {
  2736.             // Yep, this is a hyperlinking node, so hint it
  2737.             //
  2738.             // Get the element
  2739.             CSmilAAnchorElement* pAnchor = (CSmilAAnchorElement*) pNode->m_pElement;
  2740.             if (pAnchor)
  2741.             {
  2742.                 // Hint this hyperlink
  2743.                 HintHyperlinkNode(pAnchor);
  2744.             }
  2745.         }
  2746.         // Now recursively check our children
  2747.         if (pNode->m_pNodeList)
  2748.         {
  2749.             LISTPOSITION pos = pNode->m_pNodeList->GetHeadPosition();
  2750.             while (pos)
  2751.             {
  2752.                 SMILNode* pChildNode = (SMILNode*) pNode->m_pNodeList->GetNext(pos);
  2753.                 HintHyperlinkNodeRecurse(pChildNode);
  2754.             }
  2755.         }
  2756.     }
  2757. }
  2758. void CSmilDocumentRenderer::HintHyperlinkNode(CSmilAAnchorElement* pAnchor)
  2759. {
  2760.     // Only hint if we actually have an href
  2761.     if(pAnchor && pAnchor->m_href.GetLength() > 0 && m_pParent)
  2762.     {
  2763.         // Get the IHXPlayer
  2764.         IHXPlayer* pPlayer = m_pParent->getPlayer();
  2765.         if(pPlayer)
  2766.         {
  2767.             // Intialize target and sendTo
  2768.             const char* pTarget = "_player";
  2769.             if (pAnchor->m_bExternal)
  2770.             {
  2771.                 if (pAnchor->m_target.GetLength() > 0)
  2772.                 {
  2773.                     pTarget = (const char*) pAnchor->m_target;
  2774.                 }
  2775.                 else
  2776.                 {
  2777.                     pTarget = "_browser";
  2778.                 }
  2779.             }
  2780.             const char* pSendTo = NULL;
  2781.             if (pAnchor->m_sendTo.GetLength() > 0)
  2782.             {
  2783.                 pSendTo = (const char*) pAnchor->m_sendTo;
  2784.             }
  2785.             BOOL bIsOnLoadActuation = FALSE;
  2786.             if (!strcmp(pAnchor->m_actuate, "onLoad"))
  2787.             {
  2788.                 bIsOnLoadActuation = TRUE;
  2789.             }
  2790.             BOOL bNeedToTargetANamedPlayerInstance = FALSE;
  2791.             if (pAnchor->m_target.GetLength() > 0)
  2792.             {
  2793.                 if (!pAnchor->m_bTargetIsARegion  &&  !pAnchor->m_bExternal)
  2794.                 {
  2795.                     bNeedToTargetANamedPlayerInstance = TRUE;
  2796.                 }
  2797.             }
  2798.             if(pAnchor->m_href[0] != '#')
  2799.             {
  2800.                 IHXHyperNavigate* pHyper = 0;
  2801.                 SMILLinkPlaystate sourcePlaystate = SMILLinkPlaystatePause;
  2802.                 if (("pause"   == pAnchor->m_show  ||
  2803.                      "replace" == pAnchor->m_show)  &&
  2804.                     !pAnchor->m_bExternal)
  2805.                 {
  2806.                     sourcePlaystate = SMILLinkPlaystatePause;
  2807.                 }
  2808.                 else
  2809.                 {
  2810.                     sourcePlaystate = pAnchor->m_sourcePlaystate;
  2811.                 }
  2812.                 BOOL bIsOldSMIL1ShowEqualsPause = FALSE;
  2813.                 if ("pause" == pAnchor->m_show)
  2814.                 {
  2815.                     bIsOldSMIL1ShowEqualsPause = TRUE;
  2816.                 }
  2817.                 CHXString urlString;
  2818.                 convertURL((const char*) m_pParent->getURLRoot(),
  2819.                            (const char*) m_pParent->getURLPrefix(),
  2820.                            (const char*) pAnchor->m_href,
  2821.                            urlString);
  2822.                 BOOL bIsMailtoURL = !(strncmp("mailto:", urlString, 7));
  2823.                 if (bIsMailtoURL)
  2824.                 {
  2825.                     pTarget = "_browser";
  2826.                 }
  2827.                 BOOL bIsCommandOpenWindowURL = FALSE;
  2828.                 // /Now, if show="new", we need to create a new player
  2829.                 // and open the URL in it:
  2830.                 // This is also true of the old SMIL 1.0 show="pause":
  2831.                 BOOL bIsCommandURL = !(strncmp("command:", urlString, 8));
  2832.                 if (bIsCommandURL)
  2833.                 {
  2834.                     const char* pCommandAction = ((const char*)urlString)+8;
  2835.                     // /Look for "command:[s*]openwindow" where [s*] is 0
  2836.                     // or more white-space characters:
  2837.                     while (isspace(*pCommandAction))
  2838.                     {
  2839.                         pCommandAction++;
  2840.                     }
  2841.                     if (*pCommandAction)
  2842.                     {
  2843.                         bIsCommandOpenWindowURL = !(strnicmp("openWindow",
  2844.                             pCommandAction, 10));
  2845.                     }
  2846.                 }
  2847.                 if (!bIsCommandURL  &&
  2848.                     (!strncmp("new", pAnchor->m_show,3) ||
  2849.                      bIsOldSMIL1ShowEqualsPause         ||
  2850.                      bNeedToTargetANamedPlayerInstance))
  2851.                 {
  2852.                     if (pAnchor->m_bExternal)
  2853.                     {
  2854.                         if(HXR_OK == pPlayer->QueryInterface(
  2855.                                 IID_IHXHyperNavigate, (void**)&pHyper))
  2856.                         {
  2857.                             // XXXMEH - use updated method which checks
  2858.                             // for <rn:param> children
  2859.                             GoToURLWithParamCheck(urlString, pTarget, pSendTo,
  2860.                                                   pHyper, pAnchor, m_pContext,
  2861.                                                   !bIsOnLoadActuation,
  2862.                                                   TRUE); // TRUE means we're hinting
  2863.                             pHyper->Release();
  2864.                         }
  2865.                     }
  2866.                     else
  2867.                     {
  2868.                         // /Have the TLC create a new player for us via
  2869.                         // "command:openWindow(windowName,URL,behavior)":
  2870.                         CHXString pOpenWindowURL = "command:openWindow(";
  2871.                         // /Now, add the "target", if specified:
  2872.                         if (pAnchor->m_target.GetLength() > 0)
  2873.                         {
  2874.                             pOpenWindowURL += pAnchor->m_target;
  2875.                         }
  2876.                         // /Otherwise, we need to make up a unique name:
  2877.                         else
  2878.                         {
  2879.                             pOpenWindowURL += pAnchor->m_pNode->m_id;
  2880.                             char* pTmp = new char[64];
  2881.                             ULONG32 ulCurTime = HX_GET_TICKCOUNT();
  2882.                             itoa(ulCurTime, pTmp, 16);
  2883.                             pOpenWindowURL += pTmp;
  2884.                             delete [] pTmp;
  2885.                         }
  2886.                         pOpenWindowURL += ",";
  2887.                         pOpenWindowURL += urlString;
  2888.                         // /Set the source (current) player's behavior:
  2889.                         switch (sourcePlaystate)
  2890.                         {
  2891.                             case SMILLinkPlaystatePlay:
  2892.                             {
  2893.                                 pOpenWindowURL += ",behavior=continue";
  2894.                             }
  2895.                             break;
  2896.                             case SMILLinkPlaystatePause:
  2897.                             {
  2898.                                 pOpenWindowURL += ",behavior=pause";
  2899.                             }
  2900.                             break;
  2901.                             case SMILLinkPlaystateStop:
  2902.                             {
  2903.                                 pOpenWindowURL += ",behavior=stop";
  2904.                             }
  2905.                             break;
  2906.                             default:
  2907.                             {
  2908.                                 HX_ASSERT(0&&"bad sourcePlaystate");
  2909.                             }
  2910.                             break;
  2911.                         }
  2912.                         pOpenWindowURL += ")";
  2913.                         if(HXR_OK == pPlayer->QueryInterface(
  2914.                                 IID_IHXHyperNavigate, (void**)&pHyper))
  2915.                         {
  2916.                             GoToURLWithParamCheck(pOpenWindowURL, pTarget, 
  2917.                                                   NULL, pHyper, pAnchor,
  2918.                                                   m_pContext, !bIsOnLoadActuation,
  2919.                                                   TRUE); // TRUE means we're hinting
  2920.                             pHyper->Release();
  2921.                         }
  2922.                     }
  2923.                 }
  2924.                 else if (pAnchor->m_bExternal  ||
  2925.                          bIsCommandURL         ||
  2926.                          bIsMailtoURL          ||
  2927.                          bIsCommandOpenWindowURL)
  2928.                 {
  2929.                     if(HXR_OK == pPlayer->QueryInterface(
  2930.                             IID_IHXHyperNavigate, (void**)&pHyper))
  2931.                     {
  2932.                         GoToURLWithParamCheck(urlString, pTarget, pSendTo,
  2933.                                               pHyper, pAnchor, m_pContext,
  2934.                                               !bIsOnLoadActuation,
  2935.                                               TRUE); // TRUE means we're hinting
  2936.                         HX_RELEASE(pHyper);
  2937.                     }
  2938.                 }
  2939.             }
  2940.         }
  2941.     }
  2942. }
  2943. void
  2944. CSmilDocumentRenderer::CleanUpSiteInfoContainers()
  2945. {    
  2946.     HX_DELETE(m_pSiteInfoByRendererMap);
  2947.     // /For PR 116482: this needs to get deleted after
  2948.     // m_pSiteInfoByRendererMap, above.  In case our close() gets called
  2949.     // before our SiteUserDetachSite() gets called, we still might have these
  2950.     // objects to delete:
  2951.     if (m_pSiteInfoList)
  2952.     {
  2953.         CHXSimpleList::Iterator i = m_pSiteInfoList->Begin();
  2954.         for(; i != m_pSiteInfoList->End(); ++i)
  2955.         {
  2956.             SMILSiteInfo* pSiteInfo = (SMILSiteInfo*)(*i);
  2957.             delete pSiteInfo;
  2958.         }
  2959.     }
  2960.     HX_DELETE(m_pSiteInfoList);
  2961. }