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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: sitemgr.cpp,v 1.6.8.1 2004/07/09 02:08:40 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. /****************************************************************************
  50.  * 
  51.  *  Basic PN implementation of the IHXSite classes.
  52.  *
  53.  *
  54.  */
  55. #include "hxcom.h"
  56. #include "hxtypes.h"
  57. #include "hxwintyp.h"
  58. #include "hxmap.h"
  59. #include "hxwin.h"
  60. #include "hxengin.h"
  61. #include "chxxtype.h"
  62. #include "hxsite2.h"
  63. #include "ihxpckts.h"
  64. #include "hxslist.h"
  65. #include "sitemgr.h"
  66. #include "siteprxy.h"
  67. #include "hxvctrl.h"
  68. #include "hxvsurf.h"
  69. #ifndef _WINCE
  70. #ifdef _WINDOWS
  71. #ifdef _WIN32
  72. #include <vfw.h>
  73. #else
  74. #include <drawdib.h>
  75. #endif /* _WIN32 */
  76. #endif /* _WINDOWS */
  77. #if defined(_MACINTOSH)
  78. #include "maclibrary.h"
  79. #include "hx_moreprocesses.h"
  80. #endif
  81. #endif
  82. #include "hxstrutl.h"
  83. #include "hxheap.h"
  84. #ifdef _DEBUG
  85. #undef HX_THIS_FILE
  86. static const char HX_THIS_FILE[] = __FILE__;
  87. #endif
  88. #if !defined(HELIX_CONFIG_NOSTATICS)
  89. INT32 CHXSiteManager::zm_nSiteManagerCount = 0;
  90. #else
  91. #include "globals/hxglobals.h"
  92. const INT32 CHXSiteManager::zm_nSiteManagerCount = 0;
  93. #endif
  94. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  95. CHXSimpleList CHXSiteManager::zm_SiteManagerList;
  96. #endif
  97. #ifdef _MACINTOSH
  98. BOOL  CHXSiteManager::zm_bWindowRemovedFromList = FALSE;
  99. #endif
  100. /************************************************************************
  101.  *  Method:
  102.  *    Destructor
  103.  */
  104. CHXSiteManager::CHXSiteManager()
  105.     : m_lRefCount(0)
  106.     , m_bInUnHookAll(FALSE)
  107.     , m_bNeedFocus(FALSE)
  108. {
  109. #if defined(HELIX_CONFIG_NOSTATICS)
  110.     INT32& zm_nSiteManagerCount =
  111. HXGlobalInt32::Get(&CHXSiteManager::zm_nSiteManagerCount);
  112. #endif
  113.     
  114. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  115.     zm_SiteManagerList.AddTail(this);
  116.     zm_nSiteManagerCount++;
  117. #endif
  118. };
  119. /************************************************************************
  120.  *  Method:
  121.  *    Destructor
  122.  */
  123. CHXSiteManager::~CHXSiteManager()
  124. {
  125. #if defined(HELIX_CONFIG_NOSTATICS)
  126.     INT32& zm_nSiteManagerCount =
  127. HXGlobalInt32::Get(&CHXSiteManager::zm_nSiteManagerCount);
  128. #endif
  129.     
  130. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  131.     LISTPOSITION pos = zm_SiteManagerList.Find(this);
  132.     zm_SiteManagerList.RemoveAt(pos);
  133.     
  134.     zm_nSiteManagerCount--;
  135. #endif
  136.     HX_ASSERT(m_MasterListOfSites.IsEmpty());
  137.     HX_ASSERT(m_SitesToSUS.IsEmpty());
  138.     RemoveMapStrToObj(&m_ChannelsToLists);
  139.     RemoveMapStrToObj(&m_PersistentChannelsToLists);
  140.     RemoveMapStrToObj(&m_LSGNamesToLists);
  141.     RemoveMapStrToObj(&m_PersistentLSGNamesToLists);
  142.     CHXMapStringToOb::Iterator ndx = m_EventHookMap.Begin();
  143.     for (; ndx != m_EventHookMap.End(); ++ndx)
  144.     {
  145.         RemoveList((CHXSimpleList*)*ndx);
  146. delete (CHXSimpleList*)*ndx;
  147.     }
  148.     m_EventHookMap.RemoveAll();
  149.     RemoveList(&m_UnnamedEventHookList);
  150.     CleanupPendingValues();
  151. }
  152. HX_RESULT   
  153. CHXSiteManager::ProcessSiteEvent(CHXEventHookElement* pElement, IHXSite* pSite, 
  154.                                  HXxEvent* pEvent, EVENT_TYPE event_type)
  155. {
  156.     HX_RESULT   rc = HXR_OK;
  157.     if (pElement)
  158.     {
  159.         switch (event_type)
  160.         {
  161.         case SITE_EVENT_GENERAL:
  162.     rc = pElement->m_pHook->HandleEvent(pSite, pEvent);
  163.             break;
  164.         case SITE_EVENT_REMOVED:
  165.             rc = pElement->m_pHook->SiteRemoved(pSite);
  166.             break;
  167.         case SITE_EVENT_ADDED:
  168.             rc = pElement->m_pHook->SiteAdded(pSite);
  169.             break;
  170.         default:
  171.             HX_ASSERT(FALSE);
  172.             break;
  173.         }
  174.     }
  175.     return rc;
  176. }
  177. HX_RESULT
  178. CHXSiteManager::HandleSiteEvent(const char* pRegionName, IHXSite* pSite, 
  179.                                 HXxEvent* pEvent, EVENT_TYPE event_type)
  180. {
  181.     HX_RESULT   rc = HXR_OK;
  182.     // first, walk through named hooks
  183.     CHXSimpleList* pList = NULL;
  184.     if (m_EventHookMap.Lookup(pRegionName, (void*&)pList))
  185.     {
  186. CHXSimpleList::Iterator iter = pList->Begin();
  187. for (; iter != pList->End(); ++iter)
  188. {
  189.     CHXEventHookElement* pElement =
  190. (CHXEventHookElement*)(*iter);
  191.             
  192.             rc = ProcessSiteEvent(pElement, pSite, pEvent, event_type);
  193.     if (pEvent && pEvent->handled)
  194.     {
  195. break;
  196.     }
  197. }
  198.     }
  199.     // try the null hooks
  200.     if (pEvent && !pEvent->handled)
  201.     {
  202. CHXSimpleList::Iterator iter = m_UnnamedEventHookList.Begin();
  203. for (; iter != m_UnnamedEventHookList.End(); ++iter)
  204. {
  205.     CHXEventHookElement* pElement =
  206. (CHXEventHookElement*)(*iter);
  207.             rc = ProcessSiteEvent(pElement, pSite, pEvent, event_type);
  208.     if (pEvent && pEvent->handled)
  209.     {
  210. break;
  211.     }
  212. }
  213.     }
  214.     return rc;
  215. }
  216. void 
  217. CHXSiteManager::HookupHelper(CHXMapPtrToPtr* pMap, char* pActualString, BOOL bIsPersistent, 
  218.                              PTR_TYPE ptr_type, HOOK_TYPE hook_type)
  219. {
  220.     if (pMap)
  221.     {
  222.         CHXMapPtrToPtr::Iterator ndx = pMap->Begin();
  223.         for (; ndx != pMap->End(); ++ndx)
  224.         {
  225.     IHXBuffer* ptempValues = (IHXBuffer*)ndx.get_key(); 
  226.             if (HOOKUP_BY_LSGNAMEWITHSTRING == hook_type)
  227.             {
  228.                 HookupByLSGNameWithString((IHXSiteUserSupplier*) *ndx, 
  229.                                           (char*)(ptempValues->GetBuffer()), 
  230.                                           bIsPersistent);
  231.             }
  232.             else if ( !strcasecmp((char*)(ptempValues->GetBuffer()), pActualString ) ) 
  233.     {
  234.                 switch (hook_type)
  235.                 {
  236.                 case HOOKUP_BY_PLAYTOFROMWITHSTRING:
  237.                     HookupByPlayToFromWithString((IHXSiteUserSupplier*) *ndx,
  238.                                                  (char*)(ptempValues->GetBuffer()), 
  239.                                                  bIsPersistent);
  240.                     break;
  241.                 case HOOKUP_SINGLESITE_BY_LSGNAMEWITHSTRING:
  242.     HookupSingleSiteByLSGNameWithString((IHXSiteUser*) *ndx, 
  243.                                                         (char*)(ptempValues->GetBuffer()), 
  244.                                                         bIsPersistent);
  245.                     break;
  246.                 case HOOKUP_SINGLESITE_BY_PLAYTOFROMWITHSTRING:
  247.                     HookupSingleSiteByPlayToFromWithString((IHXSiteUser*) *ndx,
  248.                                                            (char*)(ptempValues->GetBuffer()), 
  249.                                                            bIsPersistent);
  250.                     break;
  251.                 default:
  252.                     HX_ASSERT(FALSE);
  253.                     break;
  254.                 }
  255.     }
  256.         }
  257.     }
  258. }
  259. void 
  260. CHXSiteManager::RemoveMapStrToObj(CHXMapStringToOb* pMap)
  261. {
  262.     if (pMap)
  263.     {
  264.         CHXMapStringToOb::Iterator ndx = pMap->Begin();
  265.         for (; ndx != pMap->End(); ++ndx)
  266.         {
  267.     CHXMapPtrToPtr* pNode = (CHXMapPtrToPtr*)(*ndx);
  268.     HX_ASSERT(pNode->IsEmpty());
  269.     delete pNode;
  270.         }
  271.         pMap->RemoveAll();
  272.     }
  273. }
  274. void 
  275. CHXSiteManager::RemoveMapPtrToPtr(CHXMapPtrToPtr* pMap)
  276. {
  277.     if (pMap)
  278.     {
  279.         CHXMapPtrToPtr::Iterator i;
  280.         for(i = pMap->Begin(); i!= pMap->End();++i)
  281.         {
  282.             IHXBuffer* pValue = (IHXBuffer*)i.get_key();
  283.     CHXSiteUserSupplierProxy* pProxy = (CHXSiteUserSupplierProxy*) *i; 
  284.     HX_RELEASE(pValue);
  285.     HX_RELEASE(pProxy);
  286.         }
  287.         pMap->RemoveAll();
  288.     }
  289. }
  290. void 
  291. CHXSiteManager::RemoveList(CHXSimpleList* pList)
  292. {
  293.     if (pList)
  294.     {
  295.         CHXSimpleList::Iterator iter = pList->Begin();
  296.         for (; iter != pList->End(); ++iter)
  297.         {
  298.     CHXEventHookElement* pElement = (CHXEventHookElement*)(*iter);
  299.     delete pElement;
  300.         }
  301.         pList->RemoveAll();
  302.     }
  303. }
  304. void CHXSiteManager::CleanupPendingValues()
  305. {
  306.     RemoveMapPtrToPtr(&m_PendingValueToSULSG);
  307.     RemoveMapPtrToPtr(&m_PendingValueToSUSingleLSG);
  308.     RemoveMapPtrToPtr(&m_PendingValueToSUPlayTo);
  309.     RemoveMapPtrToPtr(&m_PendingValueToSUSinglePlayTo);
  310. }
  311. /************************************************************************
  312.  *  Method:
  313.  *    IUnknown::QueryInterface
  314.  */
  315. STDMETHODIMP 
  316. CHXSiteManager::QueryInterface(REFIID riid, void** ppvObj)
  317. {
  318.     QInterfaceList qiList[] =
  319.         {
  320.             { GET_IIDHANDLE(IID_IHXSiteManager), (IHXSiteManager*)this },
  321.             { GET_IIDHANDLE(IID_IHXEventHookMgr), (IHXEventHookMgr*)this },
  322.             { GET_IIDHANDLE(IID_IHXSiteManager2), (IHXSiteManager2*)this },
  323.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXSiteManager*)this },
  324.         };
  325.     
  326.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  327. }
  328. /************************************************************************
  329.  *  Method:
  330.  *    IUnknown::AddRef
  331.  */
  332. STDMETHODIMP_(ULONG32) 
  333. CHXSiteManager::AddRef()
  334. {
  335.     return InterlockedIncrement(&m_lRefCount);
  336. }
  337. /************************************************************************
  338.  *  Method:
  339.  *    IUnknown::Release
  340.  */
  341. STDMETHODIMP_(ULONG32) 
  342. CHXSiteManager::Release()
  343. {
  344.     if (InterlockedDecrement(&m_lRefCount) > 0)
  345.     {
  346.         return m_lRefCount;
  347.     }
  348.     delete this;
  349.     return 0;
  350. }
  351. /************************************************************************
  352.  *  Method:
  353.  *    IHXSiteManager::AddSiteByStringHelper
  354.  */
  355. STDMETHODIMP 
  356. CHXSiteManager::AddSiteByStringHelper
  357. (
  358.     const char* pString,
  359.     IHXSite* pSite,
  360.     CHXMapStringToOb& ByStringMap
  361. )
  362. {
  363.     HRESULT     hresFinal     = HXR_OK;
  364.     void*     pVoid     = NULL;
  365.     CHXMapPtrToPtr* pSiteCollection = NULL;
  366.     /*
  367.      * The basic data structure is as follows: A map is kept 
  368.      * from names to "lists" of sites. We don't actually use
  369.      * a list because we want to quickly detect if the item is
  370.      * already in the list so we use a map for the sites as well.
  371.      */
  372.     /*
  373.      * Find the list in the name to list map, if there is no
  374.      * list in the map then we need to create a new list object
  375.      * and add it to the map.
  376.      */
  377.     if (!ByStringMap.Lookup(pString,pVoid))
  378.     {
  379. pSiteCollection = new CHXMapPtrToPtr();
  380. ByStringMap.SetAt(pString,pSiteCollection);
  381.     }
  382.     else
  383.     {
  384. pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  385.     }
  386.     /*
  387.      * Now that we have the collection of sites we want to see
  388.      * if this item is already in the collection. If it is, then
  389.      * we barf out an error!
  390.      */
  391.     if (pSiteCollection->Lookup(pSite,pVoid))
  392.     {
  393. hresFinal = HXR_INVALID_PARAMETER;
  394. goto exit;
  395.     }
  396.     /*
  397.      * Now that we know its cool to add this to the collection,
  398.      * we do just that...
  399.      */
  400.     pSiteCollection->SetAt(pSite,pSite);
  401.     /*
  402.      * We also want to keep track of which collection we added
  403.      * the site to so that we can more easily (quickly) delete
  404.      * the site when it is removed. To do this we keep a master
  405.      * map of pSite's to the pSiteList items.
  406.      *
  407.      * NOTE: This site should not already be in the master 
  408.      * list. This debug check is a sanity check since our
  409.      * previous efforts should have returned out as an error
  410.      * in the event that a site was added twice!
  411.      */
  412.     HX_ASSERT(!m_MasterListOfSites.Lookup(pSite,pVoid));
  413.     m_MasterListOfSites[pSite] = pSiteCollection;
  414. exit:
  415.     return hresFinal;
  416. }
  417. /************************************************************************
  418.  *  Method:
  419.  *    IHXSiteManager::AddSite
  420.  */
  421. STDMETHODIMP 
  422. CHXSiteManager::AddSite(IHXSite* pSite)
  423. {
  424.     IHXValues*     pProps = NULL;
  425.     IHXBuffer*     pValue = NULL;
  426.     char*     pActualString = NULL;
  427.     HRESULT     hresTemp;
  428.     HRESULT     hresFinal = HXR_OK;
  429.     BOOL     bIsPersistent = FALSE;
  430.     /*
  431.      * We need to get the IHXValues for the site so we know it
  432.      * its for by LSGName or for by plattofrom use. If this is not
  433.      * available then barf up an error.
  434.      */
  435.     hresTemp = pSite->QueryInterface(IID_IHXValues,(void**)&pProps);
  436.     if (HXR_OK != hresTemp)
  437.     {
  438. hresFinal = hresTemp;
  439. goto exit;
  440.     }
  441.     /*
  442.      * let's see if this is a persistent site...
  443.      */
  444.     hresTemp = pProps->GetPropertyCString("Persistent",pValue);
  445.     if(HXR_OK == hresTemp)
  446.     {
  447. bIsPersistent = TRUE;
  448. HX_RELEASE(pValue);
  449.     }
  450.     /*
  451.      * Now let's determine if it's by LSGName or by playtofrom.
  452.      * If one of these is not available then barf up an error.
  453.      */
  454.     /*
  455.      * If the "LayoutGroup" property exists than this is 
  456.      * a site for layout groups by LSGName.
  457.      */
  458.     hresTemp = pProps->GetPropertyCString("LayoutGroup",pValue);
  459.     if (HXR_OK == hresTemp)
  460.     {
  461. pActualString = (char*)pValue->GetBuffer();
  462. if(bIsPersistent)
  463. {
  464.     hresFinal = AddSiteByStringHelper(pActualString, pSite, m_PersistentLSGNamesToLists);
  465. }
  466. else
  467. {
  468.     hresFinal = AddSiteByStringHelper(pActualString, pSite, m_LSGNamesToLists);
  469. }
  470. goto exit;
  471.     }
  472.     /*
  473.      * If the "channel" property exists than this is 
  474.      * a site for renderers playing to a channel.
  475.      */
  476.     hresTemp = pProps->GetPropertyCString("channel",pValue);
  477.     if (HXR_OK == hresTemp)
  478.     {
  479. pActualString = (char*)pValue->GetBuffer();
  480. if(bIsPersistent)
  481. {
  482.     hresFinal = AddSiteByStringHelper(pActualString, pSite, m_PersistentChannelsToLists);
  483. }
  484. else
  485. {
  486.     hresFinal = AddSiteByStringHelper(pActualString, pSite, m_ChannelsToLists);
  487. }
  488. goto exit;
  489.     }
  490. #if 0 ////// NOT YET SUPPORTED ////////
  491.     /*
  492.      * If the "playfrom" property exists than this is 
  493.      * a site for renderers playing from a source/stream combo.
  494.      * Notice that more properties than just "playfrom" are needed
  495.      * to do the actual hookup so we pass the properties in as well.
  496.      */
  497.     hresTemp = pProps->GetPropertyCString("playfrom",pValue);
  498.     if (HXR_OK == hresTemp)
  499.     {
  500. hresFinal = AddSiteByPlayFrom(pProperties,pSite);
  501. goto exit;
  502.     }
  503. #endif
  504. exit:
  505.     /*
  506.      * Cleanup any temporary objects....
  507.      */
  508.     HX_RELEASE(pProps);
  509.     HX_RELEASE(pValue);
  510.     // hookup any leftover orphan value/sites (pending)...
  511.     // first process the LSG list        
  512.     HookupHelper(&m_PendingValueToSULSG, pActualString, bIsPersistent, 
  513.                  SITE_USER_SUPPLIER, HOOKUP_BY_LSGNAMEWITHSTRING);
  514.     // next process the Single LSG list
  515.     HookupHelper(&m_PendingValueToSUSingleLSG, pActualString, bIsPersistent, 
  516.                  SITE_USER, HOOKUP_SINGLESITE_BY_LSGNAMEWITHSTRING);
  517.     
  518.     // next process play to list
  519.     HookupHelper(&m_PendingValueToSUPlayTo, pActualString, bIsPersistent, 
  520.                  SITE_USER_SUPPLIER, HOOKUP_BY_PLAYTOFROMWITHSTRING);
  521.     // next process the Single LSG list
  522.     HookupHelper(&m_PendingValueToSUSinglePlayTo, pActualString, bIsPersistent, 
  523.                  SITE_USER, HOOKUP_SINGLESITE_BY_PLAYTOFROMWITHSTRING);
  524. #ifdef _WINDOWS
  525.     if (m_bNeedFocus && pSite)
  526.     {
  527. IHXSiteWindowless* pWindowLess = NULL;
  528. IHXSiteWindowed*   pWindowed = NULL;
  529. pSite->QueryInterface(IID_IHXSiteWindowless, (void**) &pWindowLess);
  530. if (pWindowLess)
  531. {
  532.     pWindowLess->QueryInterface(IID_IHXSiteWindowed, (void**) &pWindowed);
  533. }
  534. if (pWindowed)
  535. {
  536.     HXxWindow* pWindow = pWindowed->GetWindow();
  537.     if (pWindow && pWindow->window)
  538.     {
  539. // same logic exists in pnvideo/win/winsite.cpp: _SetFocus()
  540. HWND hTmp = ::GetForegroundWindow();
  541. if( ::IsChild(hTmp, (HWND)pWindow->window ))
  542. {
  543.     ::SetFocus((HWND)pWindow->window);
  544. }
  545.     }
  546. }
  547. HX_RELEASE(pWindowLess);
  548. HX_RELEASE(pWindowed);
  549.     }
  550. #endif
  551.     return hresFinal;
  552. }
  553. /************************************************************************
  554.  *  Method:`
  555.  *    IHXSiteManager::RemoveSite
  556.  */
  557. STDMETHODIMP 
  558. CHXSiteManager::RemoveSite(IHXSite* pSite)
  559. {
  560.     void*     pVoid     = NULL;
  561.     CHXMapPtrToPtr* pSiteCollection = NULL;
  562.     IHXValues*     pProps     = NULL;
  563.     IHXBuffer*     pValue     = NULL;
  564.     BOOL     bIsPersistent   = FALSE;
  565.     const char*     pChannelName    = NULL;
  566.     /*
  567.      * This site must have been previously added and therefore
  568.      * should be in the master list of sites.
  569.      */
  570.     if (!m_MasterListOfSites.Lookup(pSite,pVoid)) 
  571.     {
  572. return HXR_INVALID_PARAMETER;
  573.     }
  574.     /*
  575.      * determine whether the site is persistent, and get the name of
  576.      * the site so it can be removed from the channel list
  577.      */
  578.     if(HXR_OK == pSite->QueryInterface(IID_IHXValues,(void**)&pProps))
  579.     {
  580. if(HXR_OK == pProps->GetPropertyCString("Persistent", pValue))
  581. {
  582.     bIsPersistent = TRUE;
  583.     HX_RELEASE(pValue);
  584. }
  585. HX_RELEASE(pProps);
  586.     }
  587.     /*
  588.      *
  589.      */
  590.     /* If we are unhooking all sites, we do not want to unhook site here */
  591.     if (!m_bInUnHookAll)
  592.     {
  593. UnhookSite(pSite, bIsPersistent);
  594.     }
  595.     /*
  596.      * We need to remove the site from whatever collection of
  597.      * sites it is in. This means we are removing it from the
  598.      * collection of sites for it's LSGName if that is how it
  599.      * was added. Instead of determining the properties supported
  600.      * by the site to determine which collection to remove it from
  601.      * we stored the site collection in our master list. Cool, eh?
  602.      */
  603.     pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  604.     HX_ASSERT(pSiteCollection->Lookup(pSite,pVoid));
  605.     pSiteCollection->RemoveKey(pSite);
  606.     /*
  607.      * Of course we also need to remove it from the master site
  608.      * list as well.
  609.      */
  610.     m_MasterListOfSites.RemoveKey(pSite);
  611.     return HXR_OK;
  612. }
  613. STDMETHODIMP
  614. CHXSiteManager::AddEventHookElement
  615. (
  616.     CHXSimpleList*     pList,
  617.     CHXEventHookElement*    pHookElement
  618. )
  619. {
  620.     // insert element into pList
  621.     // in region/uLayer order (greater uLayer
  622.     // before lesser uLayer)
  623.     HX_RESULT rc = HXR_OK;
  624.     BOOL bInserted = FALSE;
  625.     LISTPOSITION pos = pList->GetHeadPosition();
  626.     while(pos)
  627.     {
  628. CHXEventHookElement* pElement = 
  629.     (CHXEventHookElement*)pList->GetAt(pos);
  630. if(pElement->m_uLayer <= pHookElement->m_uLayer)
  631. {
  632.     pList->InsertBefore(pos, pHookElement);
  633.     bInserted = TRUE;
  634.     break;
  635. }
  636. pList->GetNext(pos);
  637.     }
  638.     if(!bInserted)
  639.     {
  640. pList->AddTail(pHookElement);
  641.     }
  642.     return rc;
  643. }
  644. STDMETHODIMP
  645. CHXSiteManager::RemoveEventHookElement
  646. (
  647.     CHXSimpleList* pList,
  648.     IHXEventHook* pHook,
  649.     UINT16 uLayer
  650. )
  651. {
  652.     HX_RESULT rc = HXR_OK;
  653.     LISTPOSITION pos = pList->GetHeadPosition();
  654.     while(pos)
  655.     {
  656. CHXEventHookElement* pThisElement = 
  657.     (CHXEventHookElement*)pList->GetAt(pos);
  658. if(pHook == pThisElement->m_pHook && 
  659.    uLayer == pThisElement->m_uLayer)
  660. {
  661.     delete pThisElement;
  662.     pList->RemoveAt(pos);
  663.     break;
  664. }
  665. pList->GetNext(pos);
  666.     }
  667.     return rc;
  668. }
  669. /************************************************************************
  670.  *  Method:
  671.  *    IHXEventHookMgr::AddHook
  672.  */
  673. STDMETHODIMP 
  674. CHXSiteManager::AddHook
  675. (
  676.     IHXEventHook*  pHook,
  677.     const char*  pRegionName,
  678.     UINT16  uLayer
  679. )
  680. {
  681.     HX_RESULT rc = HXR_OK;
  682.     CHXEventHookElement* pElement = 
  683. new CHXEventHookElement(pHook, uLayer);
  684.     if(pRegionName && strlen(pRegionName) > 0)
  685.     {
  686. CHXSimpleList* pList = NULL;
  687. if (!m_EventHookMap.Lookup(pRegionName, (void*&)pList))
  688. {
  689.     pList = new CHXSimpleList;
  690.     m_EventHookMap[pRegionName] = pList;
  691. }
  692. rc = AddEventHookElement(pList, pElement);
  693.     }
  694.     else
  695.     {
  696. rc = AddEventHookElement(&m_UnnamedEventHookList, pElement);
  697.     }
  698.     return rc;
  699. }
  700. /************************************************************************
  701.  *  Method:
  702.  *    IHXEventHookMgr::RemoveHook
  703.  */
  704. STDMETHODIMP 
  705. CHXSiteManager::RemoveHook
  706. (
  707.     IHXEventHook*  pHook,
  708.     const char*  pRegionName,
  709.     UINT16  uLayer
  710. )
  711. {
  712.     HX_RESULT rc = HXR_OK;
  713.     if(pRegionName && strlen(pRegionName) > 0)
  714.     {
  715. CHXSimpleList* pList = NULL;
  716. if (m_EventHookMap.Lookup(pRegionName, (void*&)pList))
  717. {
  718.     rc = RemoveEventHookElement(pList, pHook, uLayer);
  719. }
  720.     }
  721.     else
  722.     {
  723. rc = RemoveEventHookElement(&m_UnnamedEventHookList, pHook, uLayer);
  724.     }
  725.     return rc;
  726. }
  727. STDMETHODIMP CHXSiteManager::GetNumberOfSites(REF(UINT32) nNumSites )
  728. {
  729.     nNumSites = m_MasterListOfSites.GetCount();
  730.     return HXR_OK;
  731. }
  732. STDMETHODIMP CHXSiteManager::GetSiteAt(UINT32 nIndex, REF(IHXSite*) pSite)
  733. {
  734.     if (!m_MasterListOfSites.GetCount())
  735.     {
  736.         return HXR_FAIL;
  737.     }
  738.     
  739.     POSITION pos = m_MasterListOfSites.GetStartPosition();
  740.     void*   pValue;
  741.     for (UINT32 i = 0; i<=nIndex; i++)
  742.     {
  743.         m_MasterListOfSites.GetNextAssoc(pos, (void*&)pSite, pValue);
  744.     }
  745.     return HXR_OK;
  746. }
  747. /************************************************************************
  748. * Method:
  749. *     CHXSiteManager::HandleHookedEvent
  750. * Purpose:
  751. *   Pass the event to interested parties
  752. */
  753. HX_RESULT
  754. CHXSiteManager::HandleHookedEvent
  755. (
  756.     const char* pRegionName,
  757.     IHXSite* pSite,
  758.     HXxEvent* pEvent
  759. )
  760. {
  761.     return HandleSiteEvent(pRegionName, pSite, pEvent, SITE_EVENT_GENERAL);
  762. }
  763. /************************************************************************
  764. * Method:
  765. *     CHXSiteManager::HookedSiteAdded
  766. * Purpose:
  767. *   Let hooks know about the added site
  768. */
  769. void
  770. CHXSiteManager::HookedSiteAdded
  771. (
  772.     const char* pRegionName,
  773.     IHXSite* pSite
  774. )
  775. {
  776.     HandleSiteEvent(pRegionName, pSite, NULL, SITE_EVENT_ADDED);
  777. }
  778. /************************************************************************
  779. * Method:
  780. *     CHXSiteManager::HookedSiteRemoved
  781. * Purpose:
  782. *   Let hooks know about the removed site
  783. */
  784. void
  785. CHXSiteManager::HookedSiteRemoved
  786. (
  787.     const char* pRegionName,
  788.     IHXSite* pSite
  789. )
  790. {
  791.     HandleSiteEvent(pRegionName, pSite, NULL, SITE_EVENT_REMOVED);
  792. }
  793. /************************************************************************
  794. * Method:
  795. *     CHXSiteManager::IsSitePresent
  796. * Purpose:
  797. *   
  798. */
  799. BOOL
  800. CHXSiteManager::IsSitePresent
  801. (
  802.     IHXSite*     pSite
  803. )
  804. {
  805.     void*   pVoid = NULL;
  806.     return m_MasterListOfSites.Lookup(pSite,pVoid);
  807. }
  808. void 
  809. CHXSiteManager::NeedFocus(BOOL bNeedFocus)
  810. {
  811.     m_bNeedFocus = bNeedFocus;
  812. }
  813. /************************************************************************
  814.  *  Method:
  815.  *    IHXSiteManager::IsSiteAvailableByStringHelper
  816.  */
  817. BOOL
  818. CHXSiteManager::IsSiteAvailableByStringHelper
  819. (
  820.     const char* pString,
  821.     CHXMapStringToOb& ByStringMap
  822. )
  823. {
  824.     BOOL     bAvailable     = FALSE;
  825.     void*     pVoid     = NULL;
  826.     CHXMapPtrToPtr* pSiteCollection = NULL;
  827.     /*
  828.      * The basic data structure is as follows: A map is kept 
  829.      * from names to "lists" of sites. We don't actually use
  830.      * a list because we want to quickly detect if the item is
  831.      * already in the list so we use a map for the sites as well.
  832.      */
  833.     /*
  834.      * Find the list in the name to list map, if there is no
  835.      * list in the map then we know it is surely not available.
  836.      */
  837.     if (!ByStringMap.Lookup(pString,pVoid))
  838.     {
  839. bAvailable = FALSE;
  840. goto exit;
  841.     }
  842.     pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  843.     /*
  844.      * Now that we have the collection of sites we want to see
  845.      * if there are any items in the collection. The collection
  846.      * may exist with no items in it.
  847.      */
  848.     if (pSiteCollection->IsEmpty())
  849.     {
  850. bAvailable = FALSE;
  851. goto exit;
  852.     }
  853.     /*
  854.      * That's all we need to know, if we get this far then we
  855.      * know there exists at least one site by this string.
  856.      */
  857.     bAvailable = TRUE;
  858. exit:
  859.     return bAvailable;
  860. }
  861. /************************************************************************
  862.  *  Method:
  863.  *    CHXSiteManager::IsSiteAvailableByLSGName
  864.  */
  865. BOOL
  866. CHXSiteManager::IsSiteAvailableByLSGName(IHXValues* pProps, BOOL bIsPersistent)
  867. {
  868.     IHXBuffer*     pValue = NULL;
  869.     char*     pActualString = NULL;
  870.     HRESULT     hresTemp;
  871.     BOOL     bAvailable = FALSE;
  872.     /*
  873.      * The properties passed here are the properties of the
  874.      * site user not the site. When associating by LSG name
  875.      * the site's "LayoutGroup" property must match the site
  876.      * users "name" property. So we get the "name" property
  877.      * from the props and look it in our LSGName list.
  878.      */
  879.     hresTemp = pProps->GetPropertyCString("name",pValue);
  880.     HX_ASSERT(HXR_OK == hresTemp);
  881.     pActualString = (char*)pValue->GetBuffer();
  882.     if(bIsPersistent)
  883.     {
  884. bAvailable = IsSiteAvailableByStringHelper(pActualString,m_PersistentLSGNamesToLists);
  885.     }
  886.     else
  887.     {
  888. bAvailable = IsSiteAvailableByStringHelper(pActualString,m_LSGNamesToLists);
  889.     }
  890.     pValue->Release();
  891.     return bAvailable;
  892. }
  893. /************************************************************************
  894.  *  Method:
  895.  *    CHXSiteManager::IsSiteAvailableByPlayToFrom
  896.  */
  897. BOOL
  898. CHXSiteManager::IsSiteAvailableByPlayToFrom(IHXValues* pProps, BOOL bIsPersistent)
  899. {
  900.     IHXBuffer*     pValue = NULL;
  901.     char*     pActualString = NULL;
  902.     HRESULT     hresTemp;
  903.     BOOL     bAvailable = FALSE;
  904.     /*
  905.      * The properties passed here are the properties of the
  906.      * site user not the site. When associating by PlayToFrom
  907.      * the site's "channel" property must match the site
  908.      * users "playto" property. So we get the "playto" property
  909.      * from the props and look it in our Channel list.
  910.      */
  911.     hresTemp = pProps->GetPropertyCString("playto",pValue);
  912.     HX_ASSERT(HXR_OK == hresTemp);
  913.     pActualString = (char*)pValue->GetBuffer();
  914.     if(bIsPersistent)
  915.     {
  916. bAvailable = IsSiteAvailableByStringHelper(pActualString,m_PersistentChannelsToLists);
  917.     }
  918.     else
  919.     {
  920. bAvailable = IsSiteAvailableByStringHelper(pActualString,m_ChannelsToLists);
  921.     }
  922.     pValue->Release();
  923.     return bAvailable;
  924. }
  925. /************************************************************************
  926.  *  Method:
  927.  *    IHXSiteManager::HookupByStringHelper
  928.  */
  929. BOOL
  930. CHXSiteManager::HookupByStringHelper
  931. (
  932.     const char*     pString,
  933.     CHXMapStringToOb&     ByStringMap,
  934.     IHXSiteUserSupplier*   pSUS,
  935.     BOOL     bIsPersistent
  936. )
  937. {
  938.     void*     pVoid     = NULL;
  939.     CHXMapPtrToPtr* pSiteCollection = NULL;
  940.     CHXMapPtrToPtr::Iterator ndxSite;
  941.     /*
  942.      * The basic data structure is as follows: A map is kept 
  943.      * from names to "lists" of sites. We don't actually use
  944.      * a list because we want to quickly detect if the item is
  945.      * already in the list so we use a map for the sites as well.
  946.      */
  947.     /*
  948.      * Find the list in the name to list map, if there is no
  949.      * list in the map then we know it is surely not available.
  950.      */
  951.     if (!ByStringMap.Lookup(pString,pVoid))
  952.     {
  953. return FALSE;
  954.     }
  955.     /*
  956.      * Now that we have the collection of sites we want to actually
  957.      * hook the site user supplier up to each site in the collection.
  958.      */
  959.     pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  960.     ndxSite = pSiteCollection->Begin();
  961.     for (; ndxSite != pSiteCollection->End(); ++ndxSite)
  962.     {
  963. IHXSite* pSite     = (IHXSite*)(*ndxSite);
  964. IHXSiteUser* pUser = NULL;
  965. // If the site has a user then we should not attempt to attach him
  966. // further, if he has a user it probably means that we have 
  967. // already attached him and we are in Wall of TVs mode.
  968. if (pSite->GetUser(pUser) != HXR_OK || !pUser)
  969. {
  970.     HookupSite2SUS(pSite, pSUS, bIsPersistent);
  971. }
  972. HX_RELEASE(pUser);
  973.     }
  974.     return TRUE;
  975. }
  976. //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\.
  977. ////\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//.
  978. /************************************************************************
  979.  *  Method:
  980.  *    IHXSiteManager::HookupSite2SUS
  981.  */
  982. BOOL
  983. CHXSiteManager::HookupSite2SUS
  984. (
  985.     IHXSite*     pSite, 
  986.     IHXSiteUserSupplier*   pSUS,
  987.     BOOL     bIsPersistent
  988. )
  989. {
  990.     BOOL     retVal     = TRUE;
  991.     void*     pVoid     = NULL;
  992.     IHXSiteWindowed*     pSiteWindowed   = NULL;
  993.     IHXSiteUser*     pUser     = NULL;
  994.     BOOL     bWindowed     = FALSE;
  995.     BOOL     bNeedsWindowed  = FALSE;
  996.     /*
  997.      * We need to find out if this site user needs windowed
  998.      * sites. The first step is to determine if this is a
  999.      * windowed site.
  1000.      */
  1001.     bWindowed = (HXR_OK == pSite->QueryInterface(
  1002. IID_IHXSiteWindowed,
  1003. (void**)&pSiteWindowed));
  1004.     HX_RELEASE(pSiteWindowed);
  1005.     /*
  1006.      * If the site user supplier needs windowed sites and this
  1007.      * site is windowed, or if the site user supplier can handle
  1008.      * windowless sites, then proceed.
  1009.      */
  1010.     bNeedsWindowed = pSUS->NeedsWindowedSites();
  1011.     if (!bNeedsWindowed || (bNeedsWindowed && bWindowed))
  1012.     {
  1013. /*
  1014.  * Ask the site user supplier to create a new site user
  1015.  * for this particular site.
  1016.  */
  1017. if (HXR_OK == pSUS->CreateSiteUser(pUser))
  1018. {
  1019.     /*
  1020.      * Now actually hook up the site to the site user!
  1021.      *
  1022.      * NOTE: The IHXSite is responsible for calling the
  1023.      *      IHXSiteUser::AttachSite() method.
  1024.      *
  1025.      * NOTE: If this is a layout site user than it will
  1026.      *      create child site in response to the AttachSite()
  1027.      *      method call.
  1028.      */
  1029.     pSite->AttachUser(pUser);
  1030.     /*
  1031.      * We also record the site's that we have created users for
  1032.      * here so that we can unhook everything the next time the
  1033.      * layout is changed. We record the site user supplier
  1034.      * that created the site user so that we can delete that user
  1035.      * as well. NOTE: we shouldn't have already created this
  1036.      * user!
  1037.      */
  1038.     if(bIsPersistent)
  1039.     {
  1040. HX_ASSERT(!m_PersistentSitesToSUS.Lookup(pSite,pVoid));
  1041. m_PersistentSitesToSUS[pSite] = pSUS;
  1042.     }
  1043.     else
  1044.     {
  1045. HX_ASSERT(!m_SitesToSUS.Lookup(pSite,pVoid));
  1046. m_SitesToSUS[pSite] = pSUS;
  1047.     }
  1048.     pSite->AddRef();
  1049.     pSUS->AddRef();
  1050.     pUser->Release();
  1051. }
  1052. else
  1053. {
  1054.     retVal = FALSE;
  1055. }
  1056.     }
  1057.     else
  1058.     {
  1059. retVal = FALSE;
  1060.     }
  1061.     return retVal;
  1062. }
  1063. /************************************************************************
  1064.  *  Method:
  1065.  *    CHXSiteManager::HookupByLSGNameWithString
  1066.  */
  1067. BOOL 
  1068. CHXSiteManager::HookupByLSGNameWithString
  1069. (
  1070.     IHXSiteUserSupplier*   pSUS, 
  1071.     char*     pActualString,
  1072.     BOOL     bIsPersistent
  1073. )
  1074. {
  1075.     BOOL res = FALSE;
  1076.     if(bIsPersistent)
  1077.     {
  1078. res = HookupByStringHelper(pActualString,m_PersistentLSGNamesToLists,pSUS, bIsPersistent);
  1079. if(!res)
  1080. {
  1081.     // check for existence of string in non-persistent list, then move it if it exists
  1082.     void* pVoid = NULL;
  1083.     if(m_LSGNamesToLists.Lookup(pActualString, pVoid))
  1084.     {
  1085. m_LSGNamesToLists.RemoveKey(pActualString);
  1086. m_PersistentLSGNamesToLists.SetAt(pActualString, pVoid);
  1087. res = HookupByStringHelper(pActualString,m_PersistentLSGNamesToLists,pSUS, bIsPersistent);
  1088.     }
  1089. }
  1090.     }
  1091.     else
  1092.     {
  1093. res = HookupByStringHelper(pActualString,m_LSGNamesToLists,pSUS, bIsPersistent);
  1094.     }
  1095.     return res;
  1096. }
  1097. /************************************************************************
  1098.  *  Method:
  1099.  *    CHXSiteManager::HookupByLSGName
  1100.  */
  1101. BOOL 
  1102. CHXSiteManager::HookupByLSGName
  1103. (
  1104.     IHXSiteUserSupplier*   pSUS, 
  1105.     IHXValues*     pProps,
  1106.     BOOL     bIsPersistent
  1107. )
  1108. {
  1109.     IHXBuffer*     pValue = NULL;
  1110.     char*     pActualString = NULL;
  1111.     HRESULT     hresTemp;
  1112.     /*
  1113.      * This method is responsible for fully hooking up the
  1114.      * site user supplier with any and all sites associate with
  1115.      * it's LSG name. NOTE: The Properties passed in are those
  1116.      * of this site user supplier, so first thing is to map from
  1117.      * the appropriate property to the collection of sites having
  1118.      * that property. This is the same as the process for determining
  1119.      * availability.
  1120.      */
  1121.     hresTemp = pProps->GetPropertyCString("name",pValue);
  1122.     HX_ASSERT(HXR_OK == hresTemp);
  1123.     pActualString = (char*)pValue->GetBuffer();
  1124.     CHXSiteUserSupplierProxy* pProxy = new CHXSiteUserSupplierProxy(this,
  1125. pSUS, pActualString);
  1126.     pProxy->AddRef();
  1127.     BOOL res = HookupByLSGNameWithString(pProxy, pActualString, bIsPersistent);
  1128.     // when it fails, save the pProxy & pValue for pending hookup
  1129.     // which is done later during AddSite()
  1130.     if (!res)
  1131.     {
  1132. m_PendingValueToSULSG.SetAt(pValue, pProxy);
  1133.     }
  1134.     else
  1135.     {
  1136.         pValue->Release();
  1137. pProxy->Release(); // now owned by the hookup list
  1138.     }
  1139.     return res;
  1140. }
  1141. /************************************************************************
  1142.  *  Method:
  1143.  *    CHXSiteManager::HookupByPlayToFromWithSting
  1144.  */
  1145. BOOL
  1146. CHXSiteManager::HookupByPlayToFromWithString
  1147. (
  1148.     IHXSiteUserSupplier*   pSUS, 
  1149.     char*     pActualString,
  1150.     BOOL     bIsPersistent
  1151. )
  1152. {
  1153.     BOOL res = FALSE;
  1154.     if(bIsPersistent)
  1155.     {
  1156. res = HookupByStringHelper(pActualString,m_PersistentChannelsToLists,pSUS,bIsPersistent);
  1157. if(!res)
  1158. {
  1159.     // check for existence of string in non-persistent list, then move it if it exists
  1160.     void* pVoid = NULL;
  1161.     if(m_ChannelsToLists.Lookup(pActualString, pVoid))
  1162.     {
  1163. m_ChannelsToLists.RemoveKey(pActualString);
  1164. m_PersistentChannelsToLists.SetAt(pActualString, pVoid);
  1165. res = HookupByStringHelper(pActualString,m_PersistentChannelsToLists,pSUS,bIsPersistent);
  1166.     }
  1167. }
  1168.     }
  1169.     else
  1170.     {
  1171. res = HookupByStringHelper(pActualString,m_ChannelsToLists,pSUS,bIsPersistent);
  1172.     }
  1173.     return res;
  1174. }
  1175. /************************************************************************
  1176.  *  Method:
  1177.  *    CHXSiteManager::HookupByPlayToFrom
  1178.  */
  1179. BOOL
  1180. CHXSiteManager::HookupByPlayToFrom
  1181. (
  1182.     IHXSiteUserSupplier*   pSUS, 
  1183.     IHXValues*     pProps,
  1184.     BOOL     bIsPersistent
  1185. )
  1186. {
  1187.     IHXBuffer*     pValue = NULL;
  1188.     char*     pActualString = NULL;
  1189.     HRESULT     hresTemp;
  1190.     /*
  1191.      * This method is responsible for fully hooking up the
  1192.      * site user supplier with any and all sites associate with
  1193.      * it's playto/from infor. NOTE: The Properties passed in 
  1194.      * are those of this site user supplier, so first thing is 
  1195.      * to map from the appropriate property to the collection 
  1196.      * of sites having that property. This is the same as the 
  1197.      * process for determining availability.
  1198.      */
  1199.     hresTemp = pProps->GetPropertyCString("playto",pValue);
  1200.     HX_ASSERT(HXR_OK == hresTemp);
  1201.     pActualString = (char*)pValue->GetBuffer();
  1202.     CHXSiteUserSupplierProxy* pProxy = new CHXSiteUserSupplierProxy(this,
  1203. pSUS, pActualString);
  1204.     pProxy->AddRef();
  1205.     BOOL res = HookupByPlayToFromWithString(pProxy, pActualString, bIsPersistent);
  1206.     // when it fails, save the pSU & pValue for pending hookup
  1207.     // which is done later during AddSite()
  1208.     if (!res)
  1209.     {
  1210. m_PendingValueToSUPlayTo.SetAt(pValue, pProxy);
  1211.     }
  1212.     else
  1213.     {
  1214.         pValue->Release();
  1215. pProxy->Release(); // now owned by hookup list
  1216.     }
  1217.     return res;
  1218. }
  1219. void
  1220. CHXSiteManager::RemoveSitesByLSGName(IHXValues* pProps, BOOL bIsPersistent)
  1221. {
  1222.     IHXBuffer* pValue = 0;
  1223.     HX_RESULT rc = pProps->GetPropertyCString("name", pValue);
  1224.     if(HXR_OK == rc)
  1225.     {
  1226. const char* pActualString = (const char*)pValue->GetBuffer();
  1227. if(bIsPersistent)
  1228. {
  1229.     void* pVoid;
  1230.     if(m_PersistentLSGNamesToLists.Lookup(pActualString, pVoid))
  1231.     {
  1232. /*
  1233.  * Now that we have the collection of sites we want to actually
  1234.  * hook the site user supplier up to each site in the collection.
  1235.  */
  1236. CHXMapPtrToPtr* pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  1237. CHXMapPtrToPtr::Iterator ndxSite = pSiteCollection->Begin();
  1238. for (; ndxSite != pSiteCollection->End(); ++ndxSite)
  1239. {
  1240.     IHXSite* pSite = (IHXSite*)(*ndxSite);
  1241.     RemoveSite(pSite);
  1242. }
  1243. delete pSiteCollection;
  1244. m_PersistentLSGNamesToLists.RemoveKey(pActualString);
  1245.     }
  1246. }
  1247. pValue->Release();
  1248.     }
  1249. }
  1250. /************************************************************************
  1251.  *  Method:
  1252.  *    CHXSiteManager::UnhookSite
  1253.  */
  1254. void 
  1255. CHXSiteManager::UnhookSite(IHXSite* pSite, BOOL bIsPersistent)
  1256. {
  1257.     HX_ASSERT(pSite);
  1258.     /*
  1259.      * To unhook all the items we simple run through the site users
  1260.      * we created, ask them for their site, tell the site to detach
  1261.      * from the user, and tell the site user supplier to destroy the
  1262.      * site user. That's simple enough...
  1263.      */
  1264.     IHXSiteUserSupplier* pSUS  = 0;
  1265.     IHXSiteUser* pUser = 0;
  1266.     /* Check in both */
  1267.     if(m_PersistentSitesToSUS.Lookup(pSite, (void*&)pSUS))
  1268.     {
  1269. m_PersistentSitesToSUS.RemoveKey(pSite);
  1270. pSite->GetUser(pUser);
  1271. pSite->DetachUser();
  1272. if(pUser && pSUS)
  1273. {
  1274.     pSUS->DestroySiteUser(pUser);
  1275.     pSUS->Release();
  1276. }
  1277. HX_RELEASE(pUser);
  1278. HX_RELEASE(pSite);
  1279.     }
  1280.     else if(m_SitesToSUS.Lookup(pSite, (void*&)pSUS))
  1281.     {
  1282. m_SitesToSUS.RemoveKey(pSite);
  1283. pSite->GetUser(pUser);
  1284. pSite->DetachUser();
  1285. if(pUser && pSUS)
  1286. {
  1287.     pSUS->DestroySiteUser(pUser);
  1288.     pSUS->Release();
  1289. }
  1290. HX_RELEASE(pUser);
  1291. HX_RELEASE(pSite);
  1292.     }
  1293. }
  1294. /************************************************************************
  1295.  *  Method:
  1296.  *    CHXSiteManager::UnhookAll
  1297.  */
  1298. void 
  1299. CHXSiteManager::UnhookAll()
  1300. {
  1301.      m_bInUnHookAll = TRUE;
  1302.     /*
  1303.      * To unhook all the items we simple run through the site users
  1304.      * we created, ask them for their site, tell the site to detach
  1305.      * from the user, and tell the site user supplier to destroy the
  1306.      * site user. That's simple enough...
  1307.      */
  1308.     CHXMapPtrToPtr::Iterator ndxSite = m_SitesToSUS.Begin();
  1309.     for (;  ndxSite != m_SitesToSUS.End(); ++ndxSite)
  1310.     {
  1311. IHXSite* pSite = (IHXSite*)ndxSite.get_key();
  1312. IHXSiteUserSupplier* pSUS  = (IHXSiteUserSupplier*)(*ndxSite);
  1313. IHXSiteUser* pUser = NULL;
  1314. pSite->GetUser(pUser);
  1315. /*
  1316.  * Now actually unhook the site to the site user!
  1317.  *
  1318.  * NOTE: The IHXSite is responsible for calling the
  1319.  *      IHXSiteUser::DetachSite() method.
  1320.  *
  1321.  * NOTE: If this is a layout site user than it will
  1322.  *      destroy the child sites in responses to the
  1323.  *      DetachSite() method call.
  1324.  */
  1325. pSite->DetachUser();
  1326. if (pSUS)
  1327. {
  1328.     if (pUser)
  1329.     {
  1330. pSUS->DestroySiteUser(pUser);
  1331.     }
  1332.     pSUS->Release();
  1333. }
  1334. HX_RELEASE(pUser);
  1335. HX_RELEASE(pSite);
  1336.     }
  1337.     m_SitesToSUS.RemoveAll();
  1338.     CleanupPendingValues();
  1339.     m_bInUnHookAll = FALSE;
  1340. }
  1341. /************************************************************************
  1342.  *  Method:
  1343.  *    CHXSiteManager::HookupSingleSiteByLSGNameWithString
  1344.  */
  1345. BOOL 
  1346. CHXSiteManager::HookupSingleSiteByLSGNameWithString
  1347. (
  1348.     IHXSiteUser*     pSU,
  1349.     char*     pActualString,
  1350.     BOOL     bIsPersistent
  1351. )
  1352. {
  1353.     BOOL res = FALSE;
  1354.     
  1355.     if(bIsPersistent)
  1356.     {
  1357. res = HookupSingleSiteByStringHelper(pActualString,m_PersistentLSGNamesToLists,pSU,bIsPersistent);
  1358. if(!res)
  1359. {
  1360.     // check for existence of string in non-persistent list, then move it if it exists
  1361.     void* pVoid = NULL;
  1362.     if(m_LSGNamesToLists.Lookup(pActualString, pVoid))
  1363.     {
  1364. m_LSGNamesToLists.RemoveKey(pActualString);
  1365. m_PersistentLSGNamesToLists.SetAt(pActualString, pVoid);
  1366. res = HookupSingleSiteByStringHelper(pActualString,m_PersistentLSGNamesToLists,
  1367.     pSU,bIsPersistent);
  1368.     }
  1369. }
  1370.     }
  1371.     else
  1372.     {
  1373. res = HookupSingleSiteByStringHelper(pActualString,m_LSGNamesToLists,pSU,bIsPersistent);
  1374.     }
  1375.     return res;
  1376. }
  1377. /************************************************************************
  1378.  *  Method:
  1379.  *    CHXSiteManager::HookupSingleSiteByLSGName
  1380.  */
  1381. BOOL 
  1382. CHXSiteManager::HookupSingleSiteByLSGName
  1383. (
  1384.     IHXSiteUser*     pSU,
  1385.     IHXValues*     pProps,
  1386.     BOOL     bIsPersistent
  1387. )
  1388. {
  1389.     IHXBuffer*     pValue = NULL;
  1390.     char*     pActualString = NULL;
  1391.     HRESULT     hresTemp;
  1392.     /*
  1393.      * This method is responsible for fully hooking up the
  1394.      * site user supplier with any and all sites associate with
  1395.      * it's LSG name. NOTE: The Properties passed in are those
  1396.      * of this site user supplier, so first thing is to map from
  1397.      * the appropriate property to the collection of sites having
  1398.      * that property. This is the same as the process for determining
  1399.      * availability.
  1400.      */
  1401.     hresTemp = pProps->GetPropertyCString("name",pValue);
  1402.     HX_ASSERT(HXR_OK == hresTemp);
  1403.     pActualString = (char*)pValue->GetBuffer();
  1404.     CHXSiteUserProxy* pProxy = new CHXSiteUserProxy(this,
  1405. pSU, pActualString);
  1406.     pProxy->AddRef();
  1407.     BOOL res = HookupSingleSiteByLSGNameWithString(pProxy, pActualString, bIsPersistent);
  1408.     // when it fails, save the pProxy & pValue for pending hookup
  1409.     // which is done later during AddSite()
  1410.     if (!res)
  1411.     {
  1412. m_PendingValueToSUSingleLSG.SetAt(pValue, pProxy);
  1413.     }
  1414.     else
  1415.     {
  1416.         pValue->Release();
  1417. pProxy->Release(); // now owned by hookup list
  1418.     }
  1419.     return res;
  1420. }
  1421. /************************************************************************
  1422.  *  Method:
  1423.  *    CHXSiteManager::HookupSingleSiteByPlayToFromWithString
  1424.  */
  1425. BOOL
  1426. CHXSiteManager::HookupSingleSiteByPlayToFromWithString
  1427. (
  1428.     IHXSiteUser*     pSU,
  1429.     char*     pActualString,
  1430.     BOOL     bIsPersistent
  1431. )
  1432. {
  1433.     BOOL res = FALSE;
  1434.     if(bIsPersistent)
  1435.     {
  1436. res = HookupSingleSiteByStringHelper(pActualString,m_PersistentChannelsToLists,pSU,bIsPersistent);
  1437. if(!res)
  1438. {
  1439.     // check for existence of string in non-persistent list, then move it if it exists
  1440.     void* pVoid = NULL;
  1441.     if(m_ChannelsToLists.Lookup(pActualString, pVoid))
  1442.     {
  1443. m_ChannelsToLists.RemoveKey(pActualString);
  1444. m_PersistentChannelsToLists.SetAt(pActualString, pVoid);
  1445. res = HookupSingleSiteByStringHelper(pActualString,m_PersistentChannelsToLists,
  1446.     pSU,bIsPersistent);
  1447.     }
  1448. }
  1449.     }
  1450.     else
  1451.     {
  1452. res = HookupSingleSiteByStringHelper(pActualString,m_ChannelsToLists,pSU,bIsPersistent);
  1453.     }
  1454.     return res;
  1455. }
  1456. //////////////////////
  1457. // JEB: Add ret value 
  1458. /************************************************************************
  1459.  *  Method:
  1460.  *    CHXSiteManager::HookupSingleSiteByPlayToFrom
  1461.  */
  1462. BOOL
  1463. CHXSiteManager::HookupSingleSiteByPlayToFrom
  1464. (
  1465.     IHXSiteUser*     pSU,
  1466.     IHXValues*     pProps,
  1467.     BOOL     bIsPersistent
  1468. )
  1469. {
  1470.     IHXBuffer*     pValue = NULL;
  1471.     char*     pActualString = NULL;
  1472.     HRESULT     hresTemp;
  1473.     /*
  1474.      * The properties passed here are the properties of the
  1475.      * site user not the site. When associating by PlayToFrom
  1476.      * the site's "channel" property must match the site
  1477.      * users "playto" property. So we get the "playto" property
  1478.      * from the props and look it in our Channel list.
  1479.      */
  1480.     hresTemp = pProps->GetPropertyCString("playto",pValue);
  1481.     HX_ASSERT(HXR_OK == hresTemp);
  1482.     pActualString = (char*)pValue->GetBuffer();
  1483.     CHXSiteUserProxy* pProxy = new CHXSiteUserProxy(this,
  1484. pSU, pActualString);
  1485.     pProxy->AddRef();
  1486.     BOOL res = HookupSingleSiteByPlayToFromWithString(pProxy, pActualString, bIsPersistent);
  1487.     // when it fails, save the pProxy & pValue for pending hookup
  1488.     // which is done later during AddSite()
  1489.     if (!res)
  1490.     {
  1491. m_PendingValueToSUSinglePlayTo.SetAt(pValue, pProxy);
  1492.     }
  1493.     else
  1494.     {
  1495. pProxy->Release(); // now owned by hookup list
  1496.         pValue->Release();
  1497.     }
  1498.     return res;
  1499. }
  1500. /************************************************************************
  1501.  *  Method:
  1502.  *    IHXSiteManager::HookupSingleSiteByStringHelper
  1503.  */
  1504. BOOL
  1505. CHXSiteManager::HookupSingleSiteByStringHelper
  1506. (
  1507.     const char*     pString,
  1508.     CHXMapStringToOb&     ByStringMap,
  1509.     IHXSiteUser*     pSU,
  1510.     BOOL     bIsPersistent
  1511. )
  1512. {
  1513.     void* pVoid = NULL;
  1514.     CHXMapPtrToPtr* pSiteCollection = NULL;
  1515.     CHXMapPtrToPtr::Iterator ndxSite;
  1516.     IHXSite* pSite = NULL;
  1517.     IHXSiteWindowed* pSiteWindowed = NULL;
  1518.     IHXSiteUser* pUser = pSU;
  1519.     BOOL bWindowed = FALSE;
  1520.     BOOL bNeedsWindowed = FALSE;
  1521.     /*
  1522.      * The basic data structure is as follows: A map is kept 
  1523.      * from names to "lists" of sites. We don't actually use
  1524.      * a list because we want to quickly detect if the item is
  1525.      * already in the list so we use a map for the sites as well.
  1526.      */
  1527.     /*
  1528.      * Find the list in the name to list map, if there is no
  1529.      * list in the map then we know it is surely not available.
  1530.      */
  1531.     if (!ByStringMap.Lookup(pString,pVoid))
  1532.     {
  1533. /* We may get back site from the site supplier at a later time due to 
  1534.  * asynchronous nature. Make this request pending and we will try 
  1535.  * to HookupSingleSiteByStringHelper from within AddSite()
  1536.  */
  1537. return FALSE;
  1538.     }
  1539.     /*
  1540.      * Now that we have the collection of sites we want to actually
  1541.      * hook the site user supplier up to _THE_FIRST_ site in the collection.
  1542.      */
  1543.     pSiteCollection = (CHXMapPtrToPtr*)pVoid;
  1544.     ndxSite = pSiteCollection->Begin();
  1545.     pSite = (IHXSite*)(*ndxSite);
  1546.     /*
  1547.      * We need to find out if this site user needs windowed
  1548.      * sites. The first step is to determine if this is a
  1549.      * windowed site.
  1550.      */
  1551.     bWindowed = (HXR_OK == pSite->QueryInterface(
  1552. IID_IHXSiteWindowed,
  1553. (void**)&pSiteWindowed));
  1554.     HX_RELEASE(pSiteWindowed);
  1555.     
  1556.     /*
  1557.      * If the site user supplier needs windowed sites and this
  1558.      * site is windowed, or if the site user supplier can handle
  1559.      * windowless sites, then proceed.
  1560.      */
  1561.     bNeedsWindowed = pSU->NeedsWindowedSites();
  1562.     if (!bNeedsWindowed || (bNeedsWindowed && bWindowed))
  1563.     {
  1564. /*
  1565.  * Now actually hook up the site to the site user!
  1566.  *
  1567.  * NOTE: The IHXSite is responsible for calling the
  1568.  *      IHXSiteUser::AttachSite() method.
  1569.  *
  1570.  * NOTE: If this is a layout site user than it will
  1571.  *      create child site in response to the AttachSite()
  1572.  *      method call.
  1573.  */
  1574. pSite->AttachUser(pUser);
  1575. /*
  1576.  * We also record the site's that we have created users for
  1577.  * here so that we can unhook everything the next time the
  1578.  * layout is changed. We record the site user supplier
  1579.  * that created the site user so that we can delete that user
  1580.  * as well. NOTE: we shouldn't have already created this
  1581.  * user!
  1582.  */
  1583. if(bIsPersistent)
  1584. {
  1585.     HX_ASSERT(!m_PersistentSitesToSUS.Lookup(pSite,pVoid));
  1586.     /*
  1587.      * NULL means no Site User supplier was provided.
  1588.      */
  1589.     m_PersistentSitesToSUS[pSite] = NULL;
  1590. }
  1591. else
  1592. {
  1593.     HX_ASSERT(!m_SitesToSUS.Lookup(pSite,pVoid));
  1594.     /*
  1595.      * NULL means no Site User supplier was provided.
  1596.      */
  1597.     m_SitesToSUS[pSite] = NULL;
  1598. }
  1599. pSite->AddRef();
  1600.     }
  1601.     return TRUE;
  1602. }
  1603. /************************************************************************
  1604. * Method:
  1605. *     CHXSiteManager::EventOccurred
  1606. * Purpose:
  1607. *   Pass the event to appropriate sites
  1608. */
  1609. void 
  1610. CHXSiteManager::EventOccurred(HXxEvent* pEvent)
  1611. {
  1612. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  1613.     
  1614.     // xxxbobclark
  1615.     // first, try iterating through sites the old-fashioned way. If there are
  1616.     // any sites here then they'll be in the zm_SiteWindowedList list. If there
  1617.     // aren't, then try using the new pnvideo way.
  1618.     
  1619.     BOOL bHandledOldEvent = FALSE;
  1620.     
  1621. #if 0    /* XXX BOB PLEASE TAKE A LOOK */
  1622.     //determine which sites should get the event & send it over
  1623.     CHXSimpleList::Iterator ndxSite = CHXSiteWindowed::zm_SiteWindowedList.Begin();
  1624.     for (;  ndxSite != CHXSiteWindowed::zm_SiteWindowedList.End(); ++ndxSite)
  1625.     {
  1626. zm_bWindowRemovedFromList = FALSE;
  1627. CHXSiteWindowed* pSiteWindowed = (CHXSiteWindowed*)(*ndxSite);
  1628. bHandledOldEvent = TRUE;
  1629. pSiteWindowed->AddRef();
  1630. pSiteWindowed->MacEventOccurred(pEvent);
  1631. pSiteWindowed->Release();
  1632. /* If a window was removed from this list, iterate again
  1633.  * from the head. 
  1634.  * This *hack* is to avoid O(n^2) processing of events. 
  1635.  * It is required since a new URL may be opened from 
  1636.  * within MacEventOccured() call resulting in 
  1637.  * releasing one(or more) CHXSiteWindows.
  1638.  * 
  1639.  * Potential Problem: Same event may be given to the same 
  1640.  * window more than once.
  1641.  */
  1642. if (zm_bWindowRemovedFromList)
  1643. {
  1644.     zm_bWindowRemovedFromList = FALSE;
  1645.     ndxSite = CHXSiteWindowed::zm_SiteWindowedList.Begin();
  1646. }
  1647.     }
  1648. #endif
  1649.     if (!bHandledOldEvent)
  1650.     {
  1651. CHXSimpleList::Iterator siteManagerNdx = zm_SiteManagerList.Begin();
  1652. for (; siteManagerNdx != zm_SiteManagerList.End(); ++siteManagerNdx)
  1653. {
  1654.     CHXSiteManager* pSiteManager = (CHXSiteManager*)(*siteManagerNdx);
  1655.     CHXMapPtrToPtr::Iterator ndx = pSiteManager->m_MasterListOfSites.Begin();
  1656.     for (; ndx != pSiteManager->m_MasterListOfSites.End(); ++ndx)
  1657.     {
  1658. IHXSite* pSite = (IHXSite*)ndx.get_key();
  1659. IHXSiteWindowless* pSiteWindowless = NULL;
  1660. if (pSite->QueryInterface(IID_IHXSiteWindowless, (void**)&pSiteWindowless) == HXR_OK)
  1661. {
  1662.     pSiteWindowless->EventOccurred(pEvent);
  1663.     pSiteWindowless->Release();
  1664. }
  1665.     }
  1666. }
  1667.     }
  1668. #endif
  1669. }
  1670. /*
  1671.  * CHXEventHookElement methods
  1672.  */
  1673. CHXEventHookElement::CHXEventHookElement
  1674. (
  1675.     IHXEventHook*  pHook,
  1676.     UINT16     uLayer
  1677. ) : m_pHook(pHook)
  1678.   , m_uLayer(uLayer)
  1679. {
  1680.     HX_ASSERT(m_pHook);
  1681.     m_pHook->AddRef();
  1682. }
  1683. CHXEventHookElement::~CHXEventHookElement()
  1684. {
  1685.     HX_RELEASE(m_pHook);
  1686. }