// 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; }
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); }
/* * 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; }
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; }
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); }
/************************************************************************ * 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; }
/************************************************************************ * 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; }