📄 eventmgr.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#if defined(HELIX_FEATURE_EVENTMANAGER)
// include
#include "hxtypes.h"
#include "hxcom.h"
#include "hxresult.h"
#include "ihxpckts.h"
#include "hxcomm.h"
#include "hxengin.h"
#include "hxinter.h"
// pncont
#include "hxslist.h"
#include "hxmap.h"
// rmacore
#include "hxcbobj.h"
#include "eventmgr.h"
// pndebug
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
CRendererEventManager::CRendererEventManager(IUnknown* pContext)
{
m_lRefCount = 0;
m_pContext = pContext;
m_pScheduler = NULL;
m_pSinkList = NULL;
m_pSinkToFilterMap = NULL;
m_pCallback = NULL;
m_pEventQueue = NULL;
m_pEventQueueMutex = NULL;
if (m_pContext)
{
// AddRef the context
m_pContext->AddRef();
// QI for IHXCommonClassFactory
IHXCommonClassFactory* pFactory = NULL;
m_pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**) &pFactory);
if (pFactory)
{
// Create a mutex
pFactory->CreateInstance(CLSID_IHXMutex,
(void**) &m_pEventQueueMutex);
}
HX_RELEASE(pFactory);
}
}
CRendererEventManager::~CRendererEventManager()
{
Close();
}
STDMETHODIMP CRendererEventManager::QueryInterface(REFIID riid, void** ppvObj)
{
HX_RESULT retVal = HXR_OK;
if (ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXEventManager*)this },
{ GET_IIDHANDLE(IID_IHXEventManager), (IHXEventManager*)this },
{ GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*)this },
};
retVal = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
else
{
retVal = HXR_FAIL;
}
return retVal;
}
STDMETHODIMP_(ULONG32) CRendererEventManager::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(ULONG32) CRendererEventManager::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
STDMETHODIMP CRendererEventManager::AddEventSink(IHXEventSink* pSink)
{
HX_RESULT retVal = HXR_FAIL;
if (pSink)
{
// Do we have a list?
if (!m_pSinkList)
{
m_pSinkList = new CHXSimpleList();
}
if (m_pSinkList)
{
// Clear the return value
retVal = HXR_OK;
// Make sure this sink is not already on the list
if (!IsSinkInList(pSink))
{
// AddRef before we put it on the list
pSink->AddRef();
// Now put this sink on the tail of the list
m_pSinkList->AddTail((void*) pSink);
// Add an NULL entry for this sink in the map
if (!m_pSinkToFilterMap)
{
m_pSinkToFilterMap = new CHXMapPtrToPtr();
}
if (m_pSinkToFilterMap)
{
m_pSinkToFilterMap->SetAt((void*) pSink, NULL);
}
}
}
}
return retVal;
}
STDMETHODIMP CRendererEventManager::RemoveEventSink(IHXEventSink* pSink)
{
HX_RESULT retVal = HXR_OK;
if (pSink && m_pSinkList && m_pSinkList->GetCount() > 0)
{
// Remove the sink's entry in the sink-to-filter map and
// release our ref on the filter
void* pVoid = NULL;
if (m_pSinkToFilterMap &&
m_pSinkToFilterMap->Lookup((void*) pSink, pVoid))
{
// Get the key value list
CHXSimpleList* pList = (CHXSimpleList*) pVoid;
// Clear this list
ClearSinkFilterList(pList);
// Delete the rule list
HX_DELETE(pList);
// Remove the entry from the sink-to-filter map
m_pSinkToFilterMap->RemoveKey((void*) pSink);
}
// Run through the sink list and release
// the list's ref on the sink
LISTPOSITION pos = m_pSinkList->GetHeadPosition();
while (pos)
{
IHXEventSink* pListSink =
(IHXEventSink*) m_pSinkList->GetAt(pos);
if (pListSink && pListSink == pSink)
{
m_pSinkList->RemoveAt(pos);
HX_RELEASE(pListSink);
break;
}
m_pSinkList->GetNext(pos);
}
}
return retVal;
}
STDMETHODIMP CRendererEventManager::AddEventSinkFilterRule(IHXEventSink* pSink,
IHXValues* pRule)
{
HX_RESULT retVal = HXR_FAIL;
if (pSink && pRule && m_pSinkToFilterMap)
{
// Do we have an entry in the filter map? We definitely
// should, because it was initialized when the sink
// was added to the sink list. The entry can be NULL,
// but there has to be an entry.
void* pVoid = NULL;
if (m_pSinkToFilterMap->Lookup((void*) pSink, pVoid))
{
// Get the filter
CHXSimpleList* pFilter = (CHXSimpleList*) pVoid;
// If the filter is NULL, then that means
// we need to create the list and put it
// back into the map
if (!pFilter)
{
pFilter = new CHXSimpleList();
if (pFilter)
{
m_pSinkToFilterMap->SetAt((void*) pSink,
(void*) pFilter);
}
}
if (pFilter)
{
// Create the CEventSinkFilterRule object
CEventSinkFilterRule* pRuleObj =
new CEventSinkFilterRule(pRule);
if (pRuleObj)
{
// Make sure this rule is not already in the list
BOOL bPresent = FALSE;
LISTPOSITION pos = pFilter->GetHeadPosition();
while (pos)
{
CEventSinkFilterRule* pListRuleObj =
(CEventSinkFilterRule*) pFilter->GetNext(pos);
if (pListRuleObj &&
pListRuleObj->Same(pRuleObj))
{
bPresent = TRUE;
break;
}
}
// Was the rule already present?
if (!bPresent)
{
// It was NOT already present, so we
// can append it to the list of rules
pFilter->AddTail((void*) pRuleObj);
}
else
{
// It was already present, so we can
// delete this object
HX_DELETE(pRuleObj);
}
// Clear the return value
retVal = HXR_OK;
}
}
}
}
return retVal;
}
STDMETHODIMP CRendererEventManager::RemoveEventSinkFilterRule(IHXEventSink* pSink,
IHXValues* pRule)
{
HX_RESULT retVal = HXR_FAIL;
if (pSink && pRule && m_pSinkToFilterMap)
{
// Do we have an entry in the filter map? We definitely
// should, because it was initialized when the sink
// was added to the sink list. The entry can be NULL,
// but there has to be an entry.
void* pVoid = NULL;
if (m_pSinkToFilterMap->Lookup((void*) pSink, pVoid))
{
// Get the filter
CHXSimpleList* pFilter = (CHXSimpleList*) pVoid;
// Do we have a filter for this sink yet?
if (pFilter)
{
// Create a temp CEventSinkFilterRule object
// just so we can use CEventSinkFilterRule::Same()
CEventSinkFilterRule* pRuleObj =
new CEventSinkFilterRule(pRule);
if (pRuleObj)
{
// Find this rule in the list
LISTPOSITION pos = pFilter->GetHeadPosition();
while (pos)
{
CEventSinkFilterRule* pListRuleObj =
(CEventSinkFilterRule*) pFilter->GetAt(pos);
if (pListRuleObj &&
pListRuleObj->Same(pRuleObj))
{
// Remove the rule from the list
pFilter->RemoveAt(pos);
// Delete the rule object
HX_DELETE(pListRuleObj);
// Jump out of the loop
break;
}
else
{
pFilter->GetNext(pos);
}
}
// Clear the return value
retVal = HXR_OK;
}
// Delete the temporary rule
HX_DELETE(pRuleObj);
}
}
}
return retVal;
}
STDMETHODIMP CRendererEventManager::FireEvent(IHXBuffer* pURLStr,
IHXBuffer* pFragmentStr,
IHXBuffer* pEventNameStr,
IHXValues* pOtherValues)
{
HX_RESULT retVal = HXR_FAIL;
if (pURLStr && pEventNameStr)
{
// Do we have a scheduler interface?
if (!m_pScheduler && m_pContext)
{
// QI for IHXScheduler
m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
}
if (m_pScheduler)
{
// Do we have a callback?
if (!m_pCallback)
{
// Create a callback object
m_pCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)RendererEventCallback);
if (m_pCallback)
{
m_pCallback->AddRef();
}
}
if (m_pCallback)
{
// Create the event object
CRendererEvent* pEvent = new CRendererEvent(pURLStr,
pFragmentStr,
pEventNameStr,
pOtherValues);
if (pEvent)
{
// Do we have an event queue?
if (!m_pEventQueue)
{
// Create an event queue
m_pEventQueue = new CHXSimpleList();
}
if (m_pEventQueue)
{
// Lock the mutex
if (m_pEventQueueMutex) m_pEventQueueMutex->Lock();
// Put the event object on the queue
m_pEventQueue->AddTail((void*) pEvent);
// If we don't already have a callback scheduled
// then schedule one
if (!m_pCallback->GetPendingCallback())
{
m_pCallback->CallbackScheduled(m_pScheduler->RelativeEnter(m_pCallback, 0));
}
// Unlock the mutex
if (m_pEventQueueMutex) m_pEventQueueMutex->Unlock();
// Clear the return value
retVal = HXR_OK;
}
}
if (FAILED(retVal))
{
HX_DELETE(pEvent);
}
}
}
}
return retVal;
}
STDMETHODIMP CRendererEventManager::Func()
{
HX_RESULT retVal = HXR_OK;
// Lock the mutex
if (m_pEventQueueMutex) m_pEventQueueMutex->Lock();
// Fire off all the events in the event queue
if (m_pEventQueue && m_pEventQueue->GetCount() > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -