⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sinkctl.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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 ***** */ 

#include "hxcom.h"
#include "hxtypes.h"
#include "hxclsnk.h"
#include "hxengin.h"
#include "hxcore.h"
#include "hxengin.h"
#include "hxsched.h"
#include "hxerror.h"
#include "hxslist.h"
#include "hxcbobj.h"
#include "sinkctl.h"

#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif

CHXAdviseSinkControl::PlayerAdviseSink::PlayerAdviseSink(
				    IHXClientAdviseSink* pAdviseSink,
				    BOOL bInterruptSafe)
{
    m_pAdviseSink	    = pAdviseSink;
    m_pAdviseSink->AddRef();
    m_bInterruptSafe	    = bInterruptSafe;
    m_pPendingAdviseList    = NULL;
}

CHXAdviseSinkControl::PlayerAdviseSink::~PlayerAdviseSink()
{
    while (m_pPendingAdviseList && m_pPendingAdviseList->GetCount() > 0)
    {
	PendingAdvise* pPendingAdvise = 
		    (PendingAdvise*) m_pPendingAdviseList->RemoveHead();
	delete pPendingAdvise;
    }

    HX_RELEASE(m_pAdviseSink);
    HX_DELETE(m_pPendingAdviseList);
}

CHXAdviseSinkControl::CHXAdviseSinkControl()
    : m_lRefCount(0) 
    , m_pInterruptState(NULL)
{
    m_pCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)AdviseSinkCallback);
    m_pCallback->AddRef();
}

CHXAdviseSinkControl::~CHXAdviseSinkControl()
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);

    	HX_DELETE(pPlayerAdviseSink);
    }
    m_pSinkList.RemoveAll();

    HX_RELEASE(m_pInterruptState);

    if (m_pCallback && m_pScheduler)
    {
        m_pScheduler->Remove(m_pCallback->GetPendingCallback());
        m_pCallback->CallbackCanceled();
    }

    HX_RELEASE(m_pCallback);
    HX_RELEASE(m_pScheduler);
}

void
CHXAdviseSinkControl::Init(IHXClientEngine* pEngine)
{
    pEngine->QueryInterface(IID_IHXInterruptState, 
				(void**) &m_pInterruptState);
    
    pEngine->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
}

HX_RESULT   
CHXAdviseSinkControl::AddAdviseSink(IHXClientAdviseSink* pAdviseSink)
{
    IHXInterruptSafe*	pInterruptSafe	=NULL;
    BOOL		bInterruptSafe	=FALSE;
    pAdviseSink->QueryInterface(IID_IHXInterruptSafe,(void**) &pInterruptSafe);
    if (pInterruptSafe)
    {
	bInterruptSafe=pInterruptSafe->IsInterruptSafe();
	pInterruptSafe->Release();
    }

    PlayerAdviseSink* pPlayerAdviseSink = new PlayerAdviseSink(pAdviseSink, 
							bInterruptSafe);
    m_pSinkList.AddTail(pPlayerAdviseSink);

    return HXR_OK;
}

HX_RESULT   
CHXAdviseSinkControl::RemoveAdviseSink(IHXClientAdviseSink* pAdviseSink)
{
    PlayerAdviseSink* pPlayerAdviseSink;
    CHXSimpleList::Iterator lIterator	= m_pSinkList.Begin();
    for (; lIterator != m_pSinkList.End(); ++lIterator)
    {
	pPlayerAdviseSink = (PlayerAdviseSink*) (*lIterator);
    	if (pPlayerAdviseSink->m_pAdviseSink == pAdviseSink)
    	{
	    LISTPOSITION pos = m_pSinkList.Find(pPlayerAdviseSink);
	    m_pSinkList.RemoveAt(pos);	    
	    HX_DELETE(pPlayerAdviseSink);
	    return HXR_OK;
    	}
    }

    return HXR_FAIL;
}



//
//	This object is never interrupt safe
//	and thus cannot be called at interrupt time.
//
STDMETHODIMP_(BOOL) CHXAdviseSinkControl::IsInterruptSafe()
{
	return FALSE;
}
	
// *** IUnknown methods ***

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::QueryInterface
//  Purpose:
//	Implement this to export the interfaces supported by your 
//	object.
//
STDMETHODIMP CHXAdviseSinkControl::QueryInterface(REFIID riid, void** ppvObj)
{
    QInterfaceList qiList[] =
        {
            { GET_IIDHANDLE(IID_IHXClientAdviseSink), (IHXClientAdviseSink*)this },
            { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*)this },
            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXClientAdviseSink*)this },
        };
    
    return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::AddRef
//  Purpose:
//	Everyone usually implements this the same... feel free to use
//	this implementation.
//
STDMETHODIMP_(ULONG32) CHXAdviseSinkControl::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::Release
//  Purpose:
//	Everyone usually implements this the same... feel free to use
//	this implementation.
//
STDMETHODIMP_(ULONG32) CHXAdviseSinkControl::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}


void
CHXAdviseSinkControl::AddToPendingList(PlayerAdviseSink* pPlayerAdviseSink,
				       AdviseType type,
				       UINT32 ulArg1, 
				       UINT32 ulArg2, 
				       char*  pHostName)
{
    if (!pPlayerAdviseSink->m_pPendingAdviseList)
    {
	pPlayerAdviseSink->m_pPendingAdviseList = new CHXSimpleList;
    }

    PendingAdvise* pPendingAdvise = new PendingAdvise;
    pPendingAdvise->m_AdviseType = type;
    pPendingAdvise->m_ulArg1 = ulArg1;
    pPendingAdvise->m_ulArg2 = ulArg2;

    if (pHostName)
    {
	pPendingAdvise->m_pHostName = new char[strlen(pHostName) + 1];
	strcpy(pPendingAdvise->m_pHostName, pHostName); /* Flawfinder: ignore */
    }

    pPlayerAdviseSink->m_pPendingAdviseList->AddTail((void*) pPendingAdvise);

    if (!m_pCallback->GetPendingCallback())
    {
        m_pCallback->CallbackScheduled(m_pScheduler->RelativeEnter(m_pCallback, 0));
    }
}

void
CHXAdviseSinkControl::ProcessAllRequests(void)
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	ProcessPendingRequests(pPlayerAdviseSink);
    }
}

void
CHXAdviseSinkControl::ProcessPendingRequests(PlayerAdviseSink* 
						pPlayerAdviseSink)
{
    while (pPlayerAdviseSink->m_pPendingAdviseList && 
	   pPlayerAdviseSink->m_pPendingAdviseList->GetCount() > 0)
    {
	PendingAdvise* pPendingAdvise = (PendingAdvise*) 
		pPlayerAdviseSink->m_pPendingAdviseList->RemoveHead();
	switch(pPendingAdvise->m_AdviseType)
	{
	    case ONPOSLENGTH:
    		pPlayerAdviseSink->m_pAdviseSink->OnPosLength(
					    pPendingAdvise->m_ulArg1, 
					    pPendingAdvise->m_ulArg2);
		break;
	    case ONPRESENTATIONOPENED:
    		pPlayerAdviseSink->m_pAdviseSink->OnPresentationOpened();
		break;
	    case ONPRESENTATIONCLOSED:
    		pPlayerAdviseSink->m_pAdviseSink->OnPresentationClosed();
		break;
	    case ONSTATISTICSCHANGED:
    		pPlayerAdviseSink->m_pAdviseSink->OnStatisticsChanged();
		break;
	    case ONPRESEEK:
    		pPlayerAdviseSink->m_pAdviseSink->OnPreSeek(
					    pPendingAdvise->m_ulArg1, 
					    pPendingAdvise->m_ulArg2);
		break;
	    case ONPOSTSEEK:
    		pPlayerAdviseSink->m_pAdviseSink->OnPostSeek(
					    pPendingAdvise->m_ulArg1, 
					    pPendingAdvise->m_ulArg2);
		break;
	    case ONSTOP:
    		pPlayerAdviseSink->m_pAdviseSink->OnStop();
		break;
	    case ONPAUSE:
        	pPlayerAdviseSink->m_pAdviseSink->OnPause(
						pPendingAdvise->m_ulArg1);
		break;
	    case ONBEGIN:
        	pPlayerAdviseSink->m_pAdviseSink->OnBegin(
						pPendingAdvise->m_ulArg1);
		break;
	    case ONBUFFERING:
    		pPlayerAdviseSink->m_pAdviseSink->OnBuffering(
						pPendingAdvise->m_ulArg1, 
				       (UINT16)	pPendingAdvise->m_ulArg2);
		break;
	    case ONCONTACTING:
    		pPlayerAdviseSink->m_pAdviseSink->OnContacting(
				    		pPendingAdvise->m_pHostName);
		break;
	    default:
		HX_ASSERT(FALSE);
		break;
	}

	delete pPendingAdvise;
    }
}

/*
 *	IHXClientAdviseSink methods
 */

/************************************************************************
 *	Method:
 *	    IHXClientAdviseSink::OnPosLength
 *	Purpose:
 *	    Called to advise the client that the position or length of the
 *	    current playback context has changed.
 */
STDMETHODIMP
CHXAdviseSinkControl::OnPosLength(UINT32	  ulPosition,
				   UINT32	  ulLength)
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	if (!m_pInterruptState->AtInterruptTime() || 
	    pPlayerAdviseSink->m_bInterruptSafe)
	{
	    ProcessPendingRequests(pPlayerAdviseSink);
    	    pPlayerAdviseSink->m_pAdviseSink->OnPosLength(ulPosition, 
							  ulLength);
	}
	else
	{
	    AddToPendingList(pPlayerAdviseSink, ONPOSLENGTH, 
			     ulPosition, ulLength);
	}
    }

    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXClientAdviseSink::OnPresentationOpened
 *	Purpose:
 *	    Called to advise the client a presentation has been opened.
 */
STDMETHODIMP CHXAdviseSinkControl::OnPresentationOpened()
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	if (!m_pInterruptState->AtInterruptTime() || 
	    pPlayerAdviseSink->m_bInterruptSafe)
	{
	    ProcessPendingRequests(pPlayerAdviseSink);
    	    pPlayerAdviseSink->m_pAdviseSink->OnPresentationOpened();
	}
	else
	{
	    AddToPendingList(pPlayerAdviseSink, ONPRESENTATIONOPENED);
	}
    }

    return HXR_OK;
}


/************************************************************************
 *	Method:
 *	    IHXClientAdviseSink::OnPresentationClosed
 *	Purpose:
 *	    Called to advise the client a presentation has been closed.
 */
STDMETHODIMP CHXAdviseSinkControl::OnPresentationClosed()
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	if (!m_pInterruptState->AtInterruptTime() || 
	    pPlayerAdviseSink->m_bInterruptSafe)
	{
	    ProcessPendingRequests(pPlayerAdviseSink);
    	    pPlayerAdviseSink->m_pAdviseSink->OnPresentationClosed();
	}
	else
	{
	    AddToPendingList(pPlayerAdviseSink, ONPRESENTATIONCLOSED);
	}
    }

    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXClientAdviseSink::OnStatisticsChanged
 *	Purpose:
 *	    Called to advise the client that the presentation statistics
 *	    have changed. 
 */
STDMETHODIMP CHXAdviseSinkControl::OnStatisticsChanged(void)
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	if (!m_pInterruptState->AtInterruptTime() || 
	    pPlayerAdviseSink->m_bInterruptSafe)
	{
	    ProcessPendingRequests(pPlayerAdviseSink);
    	    pPlayerAdviseSink->m_pAdviseSink->OnStatisticsChanged();
	}
	else
	{
	    AddToPendingList(pPlayerAdviseSink, ONSTATISTICSCHANGED);
	}
    }

    return HXR_OK;
}

/************************************************************************
 *	Method:
 *	    IHXClientAdviseSink::OnPreSeek
 *	Purpose:
 *	    Called by client engine to inform the client that a seek is
 *	    about to occur. The render is informed the last time for the 
 *	    stream's time line before the seek, as well as the first new
 *	    time for the stream's time line after the seek will be completed.
 *
 */
STDMETHODIMP CHXAdviseSinkControl::OnPreSeek(	ULONG32	ulOldTime,
						ULONG32	ulNewTime)
{
    CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
    for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
    {
	PlayerAdviseSink* pPlayerAdviseSink = 
		    (PlayerAdviseSink*) (*lSinkerator);
	if (!m_pInterruptState->AtInterruptTime() || 
	    pPlayerAdviseSink->m_bInterruptSafe)
	{
	    ProcessPendingRequests(pPlayerAdviseSink);
    	    pPlayerAdviseSink->m_pAdviseSink->OnPreSeek(ulOldTime, 
							ulNewTime);
	}
	else
	{
	    AddToPendingList(pPlayerAdviseSink, ONPRESEEK, 
			     ulOldTime, ulNewTime);
	}
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -