예제 #1
0
// helper
static bool IsRealNetworksPlugin(HXPlugin* pPlugin)
{
    bool isRNPlugin = false;

    HX_ASSERT(pPlugin);
    IHXValues* pval = 0;
    if (SUCCEEDED(pPlugin->GetPluginInfo(pval)))
    {
        IHXBuffer* pbuff = 0;
	if (SUCCEEDED(pval->GetPropertyCString(PLUGIN_DESCRIPTION2, pbuff)))
	{
	    isRNPlugin =  (0 != strstr((const char*)pbuff->GetBuffer(), "RealNetworks"));
            HX_RELEASE(pbuff);
        }
        HX_RELEASE(pval);
    }

    return isRNPlugin;
}
예제 #2
0
HXASMStream::HXASMStream(HXStream* pStream, HXSource* pSource)
    : m_bTimeStampDeliveryMode(FALSE)
    , m_bInitialSubscribe(TRUE)
    , m_bHasExpression(FALSE)
    , m_bEndOneRuleEndAll(FALSE)
    , m_ulLastLimitBandwidth(0xffffffff)
    , m_lRefCount(0)
    , m_nNumRules(0)
    , m_pAtomicRuleChange(0)
    , m_pRuleBook(0)
    , m_pLossCB(0)
    , m_ulLossCBHandle(0)
    , m_ulBandwidthAllocation(0)
    , m_ulFixedBandwidth(0)
    , m_pSubInfo(0)
    , m_ulRuleBw(0)
    , m_ulRulePreData(0)
    , m_ulCurrentPreData(0)
    , m_ulCurrentBandwidth(0)
    , m_ulLastBandwidth(0)
    , m_bRuleTimeStampDelivery(0)
    , m_ulSubscribedBw(0)
    , m_lBias(0)
    , m_bStartRecalc(FALSE)
    , m_pSubList(0)
    , m_pSubscriptionVariables(0)
    , m_pRuleSubscribeStatus(NULL)
    , m_pASMRuleState(NULL)
    , m_pRuleEnableState(NULL)
    , m_bSubsLocked(FALSE)
#ifndef GOLD
    , m_pEM(0)
#endif
{
    m_pStreamSinkMap = new CHXMapPtrToPtr;
    
    UINT32  ulStreamID;
    IHXPlayer* pPlayer;

    pStream->GetID(ulStreamID);
    m_pSource = pSource;
    m_pSource->AddRef();
    m_pHeader = pStream->GetHeader();
    m_uStreamNumber = pStream->GetStreamNumber();

    /* Hold onto some useful interfaces */

    m_pSource->GetPlayer(pPlayer);
    pPlayer->QueryInterface(IID_IHXRegistry,  (void **)&m_pRegistry);
    pPlayer->QueryInterface(IID_IHXScheduler,   (void **)&m_pScheduler);
    pPlayer->QueryInterface(IID_IHXCommonClassFactory,   (void **)&m_pCCF);
    pPlayer->Release();

    /*
     * WARNING!  You must update all interfaces queried off the source
     * in ResetASMSource().
     */
    m_pSource->QueryInterface(IID_IHXASMSource, (void **)&m_pASMSource);
    m_pSource->QueryInterface(IID_IHXAtomicRuleChange,
	(void **)&m_pAtomicRuleChange);

#ifndef GOLD
    pPlayer->QueryInterface(IID_IHXErrorMessages, (void **)&m_pEM);
#endif

    UINT32 ulEndOneruleEndAll = 0;
    if (m_pHeader->GetPropertyULONG32("EndOneRuleEndAll", ulEndOneruleEndAll) == HXR_OK)
    {
	m_bEndOneRuleEndAll = (ulEndOneruleEndAll == 1);
    }
    /* temporary hack to properly shut down RA and RV streams with end time */
    else
    {	
	IHXBuffer* pMimeType = NULL;
	m_pHeader->GetPropertyCString("MimeType", pMimeType);

	if (pMimeType && 
	    ((::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALAUDIO_MULTIRATE_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MIME_TYPE) == 0) ||
	     (::strcasecmp((const char*) pMimeType->GetBuffer(), REALVIDEO_MULTIRATE_MIME_TYPE) == 0)))
	{
	    m_bEndOneRuleEndAll = TRUE;
	}

	HX_RELEASE(pMimeType);
    }

    /* Extract RuleBook from the stream header */

    IHXBuffer* pRuleBook = NULL;
    m_pHeader->GetPropertyCString("ASMRuleBook", pRuleBook);
    if (pRuleBook)
    {
        m_pRuleBook = new ASMRuleBook (m_pCCF, (const char *)pRuleBook->GetBuffer());

	m_nNumRules = m_pRuleBook->GetNumRules();
	m_ulRuleBw = new UINT32[m_nNumRules];
	m_ulRulePreData = new UINT32[m_nNumRules];
	m_bRuleTimeStampDelivery = new HXBOOL[m_nNumRules];
	m_pSubInfo = new HXBOOL[m_nNumRules];
	m_pRuleSubscribeStatus = new HXBOOL[m_nNumRules];
        m_pRuleEnableState = new RuleEnableState[m_nNumRules];

        for (UINT16 i = 0; i < m_nNumRules; i++)
        {
	    IHXValues*	pValues;
	    IHXBuffer* pBuffer;

	    m_pRuleBook->GetProperties(i, pValues);

	    m_ulRuleBw[i] = 0;
	    m_ulRulePreData[i] = 0;
	    m_bRuleTimeStampDelivery[i] = FALSE;
            m_pRuleEnableState[i] = resEnabled;

	    if (HXR_OK == pValues->GetPropertyCString("PreData",
		pBuffer))
	    {
		m_ulRulePreData[i] = atoi((char*)pBuffer->GetBuffer());
		pBuffer->Release();
	    }

	    if (HXR_OK == pValues->GetPropertyCString("AverageBandwidth",
		pBuffer))
	    {
		m_ulRuleBw[i] = atoi((char*)pBuffer->GetBuffer());
		pBuffer->Release();
	    }
	    else if (HXR_OK == pValues->GetPropertyCString("TimeStampDelivery",
		pBuffer))
	    {
		if ((pBuffer->GetBuffer()[0] == 'T') ||
		    (pBuffer->GetBuffer()[0] == 't'))
		{
		    // Handle TimeStamp Delivery (i.e. assume significant bandwidth)
		    m_ulRuleBw[i] = 0;
		    m_bRuleTimeStampDelivery[i] = TRUE;
		}
		pBuffer->Release();
	    }
	    else
	    {
		/* XXXSMP Temporary hack for invalid rulebooks */
		if (i == 0)
		{
		    IHXValues* pHeader = 0;

		    HX_VERIFY(pHeader = pStream->GetHeader());
		    pHeader->GetPropertyULONG32("AvgBitRate",m_ulRuleBw[i]);
		    pHeader->Release();
		}
		else
		{
		    m_ulRuleBw[i] = 0;
		}
	    }
	    pValues->Release();

            m_pSubInfo[i] = 0;
	    m_pRuleSubscribeStatus[i] = FALSE;
        }

	HXBOOL bFixed = TRUE;

	m_bHasExpression = m_pRuleBook->HasExpression();
	if (m_bHasExpression == FALSE)
	{
	    UINT16 i;
	    for (i = 0; i < m_nNumRules; i++)
	    {
		if (m_bRuleTimeStampDelivery[i] == FALSE)
		{
		    bFixed = FALSE;
		    break;
		}
	    }

	    if (bFixed)
	    {
		m_ulFixedBandwidth = 1;
	    }
	    else
	    {
		m_ulCurrentBandwidth = 0;
		for (i = 0; i < m_nNumRules; i++)
		{
		    m_ulCurrentBandwidth += m_ulRuleBw[i];
		}

		m_ulFixedBandwidth = m_ulCurrentBandwidth;
	    }
	}
    }
    else
    {
	IHXValues* pHeader = 0;

	HX_VERIFY(pHeader = pStream->GetHeader());
	HX_VERIFY(HXR_OK == pHeader->GetPropertyULONG32("AvgBitRate",
	    m_ulFixedBandwidth));
	
	m_ulCurrentBandwidth = m_ulFixedBandwidth; 

	pHeader->Release();
    }

    /* Get Registry ID's for interesting properties */
    IHXBuffer* pPropName = 0;

    // init. 
    memset(m_szRecv, 0, MAX_DISPLAY_NAME);
    memset(m_szLost, 0, MAX_DISPLAY_NAME);
    memset(m_szClipBandwidth, 0, MAX_DISPLAY_NAME);

    if( m_pRegistry )
	{
	    m_pRegistry->GetPropName(ulStreamID, pPropName);
	}
    
    if (pPropName)
    {
	SafeSprintf(m_szRecv, MAX_DISPLAY_NAME, "%s.received", pPropName->GetBuffer());
	m_ulIDRecv = m_pRegistry->GetId(m_szRecv);

	SafeSprintf(m_szLost, MAX_DISPLAY_NAME, "%s.lost", pPropName->GetBuffer());
	m_ulIDLost = m_pRegistry->GetId(m_szLost);

	SafeSprintf(m_szClipBandwidth, MAX_DISPLAY_NAME, "%s.ClipBandwidth", pPropName->GetBuffer());
	m_ulIDClipBandwidth = m_pRegistry->GetId(m_szClipBandwidth);
	pPropName->Release();
    }

    /* 
     * We consider Local source as a Network source IFF someone uses core
     * for simulated network playback (used for Preview mode in the Encoder)
     */
    if (pSource->IsLocalSource() && !pSource->IsSimulatedNetworkPlayback())
    {
	/* Some large bandwidth */
	m_ulBandwidthAllocation = 0x7FFFFFFF;
	HXBOOL b;
	SetBandwidthUsage(m_ulBandwidthAllocation, b);
    }
    else if (pSource->IsPNAProtocol())
    {
	IHXBuffer* pMimeType = NULL;
	m_pHeader->GetPropertyCString("MimeTYpe", pMimeType);

	if (pMimeType && 
	    ::strcasecmp((const char*) pMimeType->GetBuffer(), "audio/x-pn-realaudio") == 0)
	{
	    /* Some large bandwidth */
	    m_ulBandwidthAllocation = 0x7FFFFFFF;
	    HXBOOL b;
	    SetBandwidthUsage(m_ulBandwidthAllocation, b);
	}
	HX_RELEASE(pMimeType);
    }
    else if (pRuleBook)
    {
	m_pLossCB = new LossCheckCallback(this);
	m_pLossCB->AddRef();
	m_ulLossCBHandle = m_pScheduler->RelativeEnter(m_pLossCB, 1000);
    }
    
    HX_RELEASE(pRuleBook);
}
예제 #3
0
/*
* IHXBroadcastMapperResponse
*/
STDMETHODIMP
BasicSourceFinder::BroadcastTypeFound(HX_RESULT status, const char* pType)
{
    if (SF_CLOSED == m_findState)
    {
        return HXR_OK;
    }

    m_CurrentSourceType = pType;

    HX_ASSERT(m_pBroadcastMapper);
    HX_RELEASE(m_pBroadcastMapper);

    PluginHandler::BroadcastFormat* broadcast_handler;
    PluginHandler::Errors            plugin_result;
    PluginHandler::Plugin*          plugin;

    broadcast_handler =
        m_pProc->pc->plugin_handler->m_broadcast_handler;
    plugin_result = broadcast_handler->Find(pType, plugin);

    if(PluginHandler::NO_ERRORS != plugin_result)
    {
        ERRMSG(m_pProc->pc->error_handler, "No live handler for %s\n",
               pType?pType:"(null)");
        return HXR_FAIL;
    }


    /*
    * Depending on a request
    */
    HX_RESULT  theErr = HXR_FAIL;
    IHXPSourceControl* pSource = NULL;
    IHXValues* pVal = NULL;
    IHXBuffer* pBuf = NULL;

    const char* pFileName = m_pURL->name + m_pFSManager->m_mount_point_len - 1;
    UINT32     bUseSourceContainer = FALSE;
    BOOL       bUseMediaDeliveryPipeline = FALSE;

    /* XXDWL
     * For live (broadcast) sessions, the media delivery pipeline needs to be turned off.
     * This is a temporary solution until a number of issues dealing with timestamp
     * dependent media, and ASM rule handling are worked out.
     * See also: server/engine/session/player.cpp:1947

     bUseMediaDeliveryPipeline = m_pPlayerSession->m_bUseMediaDeliveryPipeline;
    */

#if NOTYET
    /* XXTDM
     * According to ghori, this was an attempt to merge the various source
     * finding code into one place.  Due to time constraints, it was never
     * finished.  Therefore, this code is currently unused and untested.
     */
    theErr = m_pRequest->GetRequestHeaders(FS_HEADERS, pVal);
    if (HXR_OK == theErr)
    {
        theErr = pVal->GetPropertyULONG32("UseSourceContainer", bUseSourceContainer);
        if (HXR_OK != theErr)
        {
            bUseSourceContainer = FALSE;
        }

        theErr = pVal->GetPropertyCString("BroadcastAlias", pBuf);
        if (HXR_OK == theErr)
        {
            pFileName = (const char*)pBuf->GetBuffer();
        }
    }
#endif /* NOTYET */

    HX_ASSERT(pFileName);
    theErr = m_pProc->pc->broadcast_manager->GetStream(pType, pFileName,
                           pSource, m_pProc, bUseMediaDeliveryPipeline,
                           m_pPlayerSession ? m_pPlayerSession->GetSessionStats()
                                            : NULL);
    if (HXR_OK == theErr)
    {
        if (bUseSourceContainer)
        {
            SourceContainer* pContainer =
                new SourceContainer(m_pProc->pc->server_context, pSource);

            if (pContainer)
            {
                pContainer->AddRef();
                FindSourceDone(HXR_OK, (IUnknown*)(IHXPSinkPackets*)pContainer);
                pContainer->Release();
            }
            else
            {
                theErr = HXR_OUTOFMEMORY;
                HX_RELEASE(pSource);
            }
        }
    }

    FindSourceDone(theErr, pSource);

    HX_RELEASE(pSource);
    HX_RELEASE(pVal);
    HX_RELEASE(pBuf);
    return HXR_OK;
}
예제 #4
0
HX_RESULT 
HXFileSystemManager::AddMountPoint(const char*	pszShortName,
					 const char* pszMountPoint,
					 IHXValues* pOptions,
					 IUnknown* pContext)
{
#if defined(HELIX_CONFIG_NOSTATICS)
    CHXSimpleList& zm_CacheList =
	HXGlobalList::Get(&HXFileSystemManager::zm_CacheList);
    CHXMapStringToOb& zm_ShortNameMap =
	HXGlobalMapStringToOb::Get(&HXFileSystemManager::zm_ShortNameMap);
    CHXMapStringToOb& zm_ProtocolMap =
	HXGlobalMapStringToOb::Get(&HXFileSystemManager::zm_ProtocolMap);
#endif

    HX_RESULT		    result	    = HXR_OK;
    IHXPlugin2Handler*	    pPlugin2Handler = NULL;
    CCacheInstance*	    pCCacheInstance = NULL;

    if (HXR_OK != pContext->QueryInterface(IID_IHXPlugin2Handler, (void**) &pPlugin2Handler))
	return HXR_FAIL;

    if (!pszShortName)
    {
	result = HXR_FAIL;
	goto cleanup;
    }
    
    UINT32 nIndex; 
    if (HXR_OK != pPlugin2Handler->FindIndexUsingStrings(PLUGIN_FILESYSTEMSHORT, 
	    (char*)pszShortName, NULL, NULL, NULL, NULL, nIndex))
    {
	result = HXR_FAIL;
	goto cleanup;
    }

    IHXValues* pValues;
    IHXBuffer* pProtocol;

    pPlugin2Handler->GetPluginInfo(nIndex, pValues);

    pValues->GetPropertyCString(PLUGIN_FILESYSTEMPROTOCOL, pProtocol);

    char*   pszProtocol;

    pszProtocol = (char*)pProtocol->GetBuffer();

    pCCacheInstance		    = new CCacheInstance;
    pCCacheInstance->m_mount_point  = pszMountPoint;
    pCCacheInstance->m_szProtocol   = pszProtocol;
    pCCacheInstance->m_szShortName  = pszShortName;
    pCCacheInstance->m_pOptions	    = pOptions;

    zm_ShortNameMap.SetAt(pszMountPoint, pCCacheInstance);
    zm_ProtocolMap.SetAt(pszMountPoint, pCCacheInstance);
    zm_CacheList.AddTail((void*)pCCacheInstance);

cleanup:

    return result;
}
예제 #5
0
void
DataRevertController::RevertHeaders(IHXValues* pFileHeader,
				    CHXSimpleList* pStreamHeaders,
				    IHXValues* pResponseHeaders)
{
    IHXBuffer* pMimeType = 0;
    IHXValues* pHeader;
    CHXSimpleList::Iterator i;
    char* pConversionType = NULL;
    IUnknown* pUnkReverter = NULL;
    HX_RELEASE(m_pDataRevert);
    
    i = pStreamHeaders->Begin();
    if (i != pStreamHeaders->End())
    {
	pHeader = (IHXValues*)(*i);
	pHeader->GetPropertyCString("MimeType", pMimeType);
	if (!pMimeType)
	{
	    HX_ASSERT(0);
	    goto exit;
	}
	if (strncasecmp((const char*)pMimeType->GetBuffer(),
		    HX_CONVERT_MIME_TYPE, (int)strlen(HX_CONVERT_MIME_TYPE)))
	{
	    goto exit;
	}
	
	pConversionType = (char*)pMimeType->GetBuffer() +
			    strlen(HX_CONVERT_MIME_TYPE);
	if (m_pPlugin2Handler &&
	    HXR_OK == m_pPlugin2Handler->FindPluginUsingStrings(
					PLUGIN_CLASS, PLUGIN_REVERTER_TYPE,
					PLUGIN_REVERTER_MIME, pConversionType,
					NULL, NULL, pUnkReverter))
	{
	    pUnkReverter->QueryInterface(IID_IHXDataRevert,
		    (void**)&m_pDataRevert);
	    pUnkReverter->Release();
	}
	if (!m_pDataRevert)
	{
	    goto exit;
	}
	IHXPlugin* pPlugin;
	m_pDataRevert->QueryInterface(IID_IHXPlugin, (void**)&pPlugin);
	pPlugin->InitPlugin(m_pContext);
	pPlugin->Release();
	HX_RELEASE(pMimeType);
	
	m_pStreamHeaders = new CHXSimpleList;
	m_pRevertedStreamHeaders = new CHXSimpleList;
	IHXBuffer* pConvertHeader = 0;
	for (i = pStreamHeaders->Begin(); i != pStreamHeaders->End(); ++i)
	{
	    pHeader = (IHXValues*)(*i);
	    /*
	     * If this stream header was converted and flattened then
	     * the one we want to give to the plugin is the result
	     * of re-inflating that.  If not, then just give the plugin
	     * the one we already got.
	     */
	    if (HXR_OK == pHeader->GetPropertyBuffer("DataConvertStreamHeader",
						    pConvertHeader))
	    {
		pHeader = InflateConvertHeader(pConvertHeader);
		pConvertHeader->Release();
	    }
	    else
	    {
		IHXBuffer* pPreConvertMimeType;
		if (HXR_OK == pHeader->GetPropertyCString("PreConvertMimeType",
							pPreConvertMimeType))
		{
		    pHeader->SetPropertyCString("MimeType",
						pPreConvertMimeType);
		    pPreConvertMimeType->Release();
		}
		pHeader->AddRef();
	    }
	    m_pStreamHeaders->AddTail((void*)pHeader);
	}
	m_pResponseHeaders = pResponseHeaders;
	m_pResponseHeaders->AddRef();
	
	/*
	 * If playing through an old proxy which does not support
	 * initiate-session then the DataConvertBuffer will come in here.
	 * This is not an ideal situation because only one can come in
	 * at this point, but it's better then nothing. 
	 */
	IHXBuffer* pConvertBuffer = 0;
	if (HXR_OK == pFileHeader->GetPropertyBuffer("DataConvertBuffer",
		    pConvertBuffer))
	{
	    const char* pContent = (const char*)pConvertBuffer->GetBuffer();
	    IHXBuffer* pNewBuffer = NULL;
	    if (HXR_OK == CreateBufferCCF(pNewBuffer, m_pContext))
	    {
		int contentLen = pConvertBuffer->GetSize();
		pNewBuffer->SetSize(contentLen);
		int offset = BinFrom64(pContent, contentLen,
				       (unsigned char*)pNewBuffer->GetBuffer());
		pNewBuffer->SetSize(offset);
		ControlBufferReady(pNewBuffer);
		HX_RELEASE(pNewBuffer);
	    }
	    HX_RELEASE(pConvertBuffer);
	}
	/*
	 * Again for file header, if the header was converted and
	 * flattened then give to plugin the inflated version of that.
	 * If not, then give the straight old header that we already
	 * have.
	 */
	if (HXR_OK == pFileHeader->GetPropertyBuffer("DataConvertFileHeader",
		    pConvertHeader))
	{
	    m_pFileHeaders = InflateConvertHeader(pConvertHeader);
	    pConvertHeader->Release();
	}
	else
	{
	    m_pFileHeaders = pFileHeader;
	    m_pFileHeaders->AddRef();
	}

	m_pDataRevert->DataRevertInit(this);
	return;
    }


exit:;
    HX_RELEASE(pMimeType);
    m_pControlResp->RevertHeadersDone(pFileHeader, 
				      pStreamHeaders,
				      pResponseHeaders,
				      FALSE);
}
예제 #6
0
/************************************************************************
 *  Method:`
 *    IHXSiteManager::RemoveSite
 */
STDMETHODIMP 
CHXSiteManager::RemoveSite(IHXSite* pSite)
{
    void*	    pVoid	    = NULL;
    CHXMapPtrToPtr* pSiteCollection = NULL;
    IHXValues*	    pProps	    = NULL;
    IHXBuffer*	    pValue	    = NULL;
    HXBOOL	    bIsPersistent   = FALSE;

    /*
     * This site must have been previously added and therefore
     * should be in the master list of sites.
     */
    if (!m_MasterListOfSites.Lookup(pSite,pVoid)) 
    {
	return HXR_INVALID_PARAMETER;
    }

    /*
     * determine whether the site is persistent, and get the name of
     * the site so it can be removed from the channel list
     */
    if(HXR_OK == pSite->QueryInterface(IID_IHXValues,(void**)&pProps))
    {
	if(HXR_OK == pProps->GetPropertyCString("Persistent", pValue))
	{
	    bIsPersistent = TRUE;
	    HX_RELEASE(pValue);
	}
	HX_RELEASE(pProps);
    }

    /*
     *
     */

    /* If we are unhooking all sites, we do not want to unhook site here */
    if (!m_bInUnHookAll)
    {
	UnhookSite(pSite, bIsPersistent);
    }

    /*
     * We need to remove the site from whatever collection of
     * sites it is in. This means we are removing it from the
     * collection of sites for it's LSGName if that is how it
     * was added. Instead of determining the properties supported
     * by the site to determine which collection to remove it from
     * we stored the site collection in our master list. Cool, eh?
     */
    pSiteCollection = (CHXMapPtrToPtr*)pVoid;
    HX_ASSERT(pSiteCollection->Lookup(pSite,pVoid));
    pSiteCollection->RemoveKey(pSite);

    /*
     * Of course we also need to remove it from the master site
     * list as well.
     */
    m_MasterListOfSites.RemoveKey(pSite);

    return HXR_OK;
}
예제 #7
0
/************************************************************************
 *  Method:
 *    IHXSiteManager::AddSite
 */
STDMETHODIMP 
CHXSiteManager::AddSite(IHXSite* pSite)
{
    IHXValues*	    pProps = NULL;
    IHXBuffer*	    pValue = NULL;
    char*	    pActualString = NULL;
    HRESULT	    hresTemp;
    HRESULT	    hresFinal = HXR_OK;
    HXBOOL	    bIsPersistent = FALSE;

    if (m_pContext)
    {
	// Give sites the same context as the site manager to allow sites to obtain
	// services specific to the environment in which they are managed (e.g. IHXCientEngine).
	IHXObjectConfiguration* pObjectConfiguration = NULL;
	if (HXR_OK == pSite->QueryInterface(IID_IHXObjectConfiguration, (void**) &pObjectConfiguration))
	{
	    pObjectConfiguration->SetContext(m_pContext);
	}
	HX_RELEASE(pObjectConfiguration);
    }
    
    /*
     * We need to get the IHXValues for the site so we know it
     * its for by LSGName or for by plattofrom use. If this is not
     * available then barf up an error.
     */
    hresTemp = pSite->QueryInterface(IID_IHXValues,(void**)&pProps);
    if (HXR_OK != hresTemp)
    {
	hresFinal = hresTemp;
	goto exit;
    }

    /*
     * let's see if this is a persistent site...
     */
    hresTemp = pProps->GetPropertyCString("Persistent",pValue);
    if(HXR_OK == hresTemp)
    {
	bIsPersistent = TRUE;
	HX_RELEASE(pValue);
    }

    /*
     * Now let's determine if it's by LSGName or by playtofrom.
     * If one of these is not available then barf up an error.
     */

    /*
     * If the "LayoutGroup" property exists than this is 
     * a site for layout groups by LSGName.
     */
    hresTemp = pProps->GetPropertyCString("LayoutGroup",pValue);
    if (HXR_OK == hresTemp)
    {
	pActualString = (char*)pValue->GetBuffer();
	if(bIsPersistent)
	{
	    hresFinal = AddSiteByStringHelper(pActualString, pSite, m_PersistentLSGNamesToLists);
	}
	else
	{
	    hresFinal = AddSiteByStringHelper(pActualString, pSite, m_LSGNamesToLists);
	}
	goto exit;
    }

    /*
     * If the "channel" property exists than this is 
     * a site for renderers playing to a channel.
     */
    hresTemp = pProps->GetPropertyCString("channel",pValue);
    if (HXR_OK == hresTemp)
    {
	pActualString = (char*)pValue->GetBuffer();
	if(bIsPersistent)
	{
	    hresFinal = AddSiteByStringHelper(pActualString, pSite, m_PersistentChannelsToLists);
	}
	else
	{
	    hresFinal = AddSiteByStringHelper(pActualString, pSite, m_ChannelsToLists);
	}
	goto exit;
    }

#if 0 ////// NOT YET SUPPORTED ////////
    /*
     * If the "playfrom" property exists than this is 
     * a site for renderers playing from a source/stream combo.
     * Notice that more properties than just "playfrom" are needed
     * to do the actual hookup so we pass the properties in as well.
     */
    hresTemp = pProps->GetPropertyCString("playfrom",pValue);
    if (HXR_OK == hresTemp)
    {
	hresFinal = AddSiteByPlayFrom(pProperties,pSite);
	goto exit;
    }
#endif

exit:
    /*
     * Cleanup any temporary objects....
     */
    HX_RELEASE(pProps);
    HX_RELEASE(pValue);

    // hookup any leftover orphan value/sites (pending)...

    // first process the LSG list	       
    HookupHelper(&m_PendingValueToSULSG, pActualString, bIsPersistent, 
                 SITE_USER_SUPPLIER, HOOKUP_BY_LSGNAMEWITHSTRING);

    // next process the Single LSG list
    HookupHelper(&m_PendingValueToSUSingleLSG, pActualString, bIsPersistent, 
                 SITE_USER, HOOKUP_SINGLESITE_BY_LSGNAMEWITHSTRING);
    
    // next process play to list
    HookupHelper(&m_PendingValueToSUPlayTo, pActualString, bIsPersistent, 
                 SITE_USER_SUPPLIER, HOOKUP_BY_PLAYTOFROMWITHSTRING);

    // next process the Single LSG list
    HookupHelper(&m_PendingValueToSUSinglePlayTo, pActualString, bIsPersistent, 
                 SITE_USER, HOOKUP_SINGLESITE_BY_PLAYTOFROMWITHSTRING);

#ifdef _WINDOWS
    if (m_bNeedFocus && pSite)
    {
	IHXSiteWindowless* pWindowLess = NULL;
	IHXSiteWindowed*   pWindowed	= NULL;

	pSite->QueryInterface(IID_IHXSiteWindowless, (void**) &pWindowLess);
	if (pWindowLess)
	{
	    pWindowLess->QueryInterface(IID_IHXSiteWindowed, (void**) &pWindowed);
	}

	if (pWindowed)
	{
	    HXxWindow* pWindow = pWindowed->GetWindow();
	    if (pWindow && pWindow->window)
	    {
		// same logic exists in pnvideo/win/winsite.cpp: _SetFocus()
		HWND hTmp = ::GetForegroundWindow();
		if( ::IsChild(hTmp, (HWND)pWindow->window ))
		{
		    ::SetFocus((HWND)pWindow->window);
		}
	    }
	}

	HX_RELEASE(pWindowLess);
	HX_RELEASE(pWindowed);
    }
#endif

    return hresFinal;
}