fswtchr.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,243 行 · 第 1/2 页

CPP
1,243
字号
/* ***** 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 ***** */ 

/****************************************************************************
 *  Includes
 */
#include "fswtchr.h"
#include "hxassert.h"
#include "qtffrefcounter.h"


/****************************************************************************
 *  Local Defines
 */
#define MAX_CHUNK_SIZE			0x0000FFFF  // 64K
#define MAX_CONSECUTIVE_FRAGMENT_LOADS	8	    // Do not set to 0



/****************************************************************************
 *  Class CFileSwitcher
 */
/****************************************************************************
 *  Constructor/Destructor
 */
CFileSwitcher::CFileSwitcher(void)
    : m_uMaxChildCount(0)
    , m_uCurrentChildCount(0)
    , m_pHandleTable(NULL)
    , m_ulFlags(0)
    , m_ulSize(0)
    , m_ulChunkSize(0)
    , m_ulProcessedSize(0)
    , m_ulFragmentCount(0)
    , m_bRelative(FALSE)
    , m_pBuffer(NULL)
    , m_pClassFactory(NULL)
    , m_pCurrentHandle(NULL)
    , m_pResponse(NULL)
    , m_pScheduler(NULL)
    , m_State(FSWCHR_Offline)
    , m_lRefCount(0)
    , m_uLastDisownedChild(0)
    , m_bClosing(FALSE)
    , m_CloseStatus(HXR_OK)
    , m_bSyncMode(FALSE)
{
    g_nRefCount_qtff++;
}


CFileSwitcher::~CFileSwitcher()
{
    Reset();
    g_nRefCount_qtff--;
}


/****************************************************************************
 *  IHXFileSwitcher private methods
 */
/****************************************************************************
 *  Reset
 */
inline void CFileSwitcher::Reset(void)
{
    HX_VECTOR_DELETE(m_pHandleTable);
    HX_RELEASE(m_pResponse);
    HX_RELEASE(m_pBuffer);
    HX_RELEASE(m_pClassFactory);
    HX_RELEASE(m_pScheduler);
    m_uCurrentChildCount = 0;
}

/****************************************************************************
 *  HandleFailureAsync
 */
HX_RESULT CFileSwitcher::HandleFailureAsync(HX_RESULT status)
{
    // Asynchronous failures occur only during Read, Write or Seek
    // process while a new FileHandle is beeing formed (since the
    // operation was requested on a file without a handle present
    // in tha HandleTable).
    HX_RESULT retVal;

    HX_ASSERT(status != HXR_OK);
    HX_ASSERT(m_pCurrentHandle);

    HX_RELEASE(m_pBuffer);

    if (m_pCurrentHandle != m_pHandleTable)
    {
	m_pCurrentHandle->Clear();
	m_uCurrentChildCount--;
    }

    switch (m_State)
    {
    case FSWCHR_ProcRead:
	retVal = ReadDone(status, NULL);
	break;
    case FSWCHR_ProcSeek:
	retVal = SeekDone(status);
	break;
    case FSWCHR_ProcWrite:
	retVal = WriteDone(status);
	break;
    case FSWCHR_ProcAdvise:
	retVal = HXR_OK;    // Silent failure
	break;
    default:
	retVal = HXR_UNEXPECTED;
	break;
    }

    return retVal;
}

/****************************************************************************
 *  HandleFailureSync
 */
HX_RESULT CFileSwitcher::HandleFailureSync(HX_RESULT status)
{
    // Synchronous failures may occur during Read, Write, Seek
    // process while a correct FileHandle is preformed and known.
    // Sync. failure also may occur during initalization of this
    // object.
    HX_ASSERT(status != HXR_OK);

    HX_RELEASE(m_pResponse);
    HX_RELEASE(m_pBuffer);

    if (m_State == FSWCHR_ProcInit)
    {
	HX_VECTOR_DELETE(m_pHandleTable);
	m_State = FSWCHR_Offline;
    }
    else
    {
	m_State = FSWCHR_Ready;
    }

    return status;
}

/****************************************************************************
 *  FindFileHandle
 */
inline CFileSwitcher::FileHandle* CFileSwitcher::FindFileHandle(const char* pFileName)
{
    FileHandle* pFileHandle;
    FileHandle* pFreeHandle = NULL;
    UINT16 uChildrenExamined;
    
    if (pFileName == NULL)
    {
	return m_pHandleTable;
    }
    
    for (uChildrenExamined = 0, pFileHandle = m_pHandleTable + 1;
	 uChildrenExamined < m_uCurrentChildCount;
	 pFileHandle++)
    {
	if (pFileHandle->m_pFileName)
	{
	    if (!strcmp(pFileHandle->m_pFileName, pFileName))
	    {
		return pFileHandle;
	    }
	    
	    uChildrenExamined++;
	}
	else
	{
	    pFreeHandle = pFileHandle;
	}
    }
    
    if (m_State == FSWCHR_ProcAdvise)
    {
	// Do not page-in on attempt to Advise. Advise must be synchronous.
	return NULL;
    }

    // Appropriate file handle wasn't found, so find a
    // free one to make a new one
    pFileHandle = pFreeHandle;
    if (m_uCurrentChildCount < m_uMaxChildCount)
    {
	pFileHandle = m_pHandleTable + m_uCurrentChildCount + 1;
	
	HX_ASSERT(!pFileHandle->m_pFileName);
	HX_ASSERT(!pFileHandle->m_pFileObject);
    }

    // make new handle
    if (pFileHandle)
    {
	if (pFileHandle->SetName(pFileName))
	{
	    m_uCurrentChildCount++;
	}
	else
	{
	    pFileHandle = NULL;
	}
    }

    return pFileHandle;
}

/****************************************************************************
 *  SelectStaleHandle
 */
inline CFileSwitcher::FileHandle* CFileSwitcher::SelectStaleHandle(void)
{
    FileHandle *pFileHandle = NULL;
    
    // Getting a stale handle is only valid when
    // there is no more room for the child handles
    HX_ASSERT(m_uMaxChildCount == m_uCurrentChildCount);

    if (m_uMaxChildCount > 0)
    {
	if (m_uLastDisownedChild < m_uMaxChildCount)
	{
	    m_uLastDisownedChild++;
	}
	else
	{
	    m_uLastDisownedChild = 1;
	}
	
	pFileHandle = m_pHandleTable + m_uLastDisownedChild;

	HX_ASSERT(pFileHandle->m_pFileName);
    }

    return pFileHandle;
}

/****************************************************************************
 *  GetFileHandle
 */
HX_RESULT CFileSwitcher::GetFileHandle(const char* pFileName)
{
    HX_RESULT retVal;

    m_pCurrentHandle = FindFileHandle(pFileName);

    if (m_pCurrentHandle)
    {
	if (m_pCurrentHandle->m_pFileObject)
	{
	    // A set-up handle exists
	    retVal = FileHandleReady();
	}
	else
	{
	    IHXGetFileFromSamePool* pFilePool;

	    // Handle was made but needs set-up
	    HX_ASSERT(m_pHandleTable->m_pFileObject);

	    retVal = m_pHandleTable->m_pFileObject->QueryInterface(
			IID_IHXGetFileFromSamePool,
			(void**) &pFilePool);

	    if (SUCCEEDED(retVal))
	    {
		// Set-up is made by duplicating the root file object
		retVal = pFilePool->GetFileObjectFromPool(
			    (IHXGetFileFromSamePoolResponse*) this);
		pFilePool->Release();
	    }
	}
    }
    else if (m_State == FSWCHR_ProcAdvise)
    {
	// Cannot advise paged-out file object
	retVal = HXR_FAIL;
    }
    else
    {
	// If the file handle table is full, select a stale
	// handle and dispose of it so the room is made for
	// the currently needed handle,
	if (m_uMaxChildCount == m_uCurrentChildCount)
	{
	    m_pCurrentHandle = SelectStaleHandle();

	    if (m_pCurrentHandle)
	    {
		m_pCurrentHandle->SetName(pFileName);

		retVal = CloseFileHandleObject(m_pCurrentHandle);
	    }
	    else
	    {
		retVal = HXR_FAIL;
	    }
	}
	else
	{
	    // We must be out memory if we failed to find or
	    // make a file handle and the file handle table
	    // still has slots available.
	    retVal = HXR_OUTOFMEMORY;
	}
    }

    if (FAILED(retVal))
    {
	retVal = HandleFailureSync(retVal);
    }

    return retVal;
}

/****************************************************************************
 *  CloseFileHandle
 */
HX_RESULT CFileSwitcher::CloseFileHandleObject(FileHandle *pFileHandle)
{
    HX_RESULT retVal;
    IHXFileObject *pFileObject;

    HX_ASSERT(pFileHandle);

    pFileObject = pFileHandle->m_pFileObject;

    if (pFileObject)
    {
	pFileHandle->m_pFileObject = NULL;

	retVal = pFileObject->Close();

	pFileObject->Release();	
    }
    else
    {
	CloseDone(HXR_OK);
	retVal = HXR_OK;
    }

    return retVal;
}

/****************************************************************************
 *  FileHandleReady
 */
HX_RESULT CFileSwitcher::FileHandleReady(void)
{
    HX_RESULT retVal;

    HX_ASSERT(m_pCurrentHandle);
    HX_ASSERT(m_pCurrentHandle->m_pFileObject);

    switch (m_State)
    {
    case FSWCHR_ProcRead:
	m_ulProcessedSize = 0;
	return ProcessRead();
    case FSWCHR_ProcSeek:
	return m_pCurrentHandle->m_pFileObject->Seek(m_ulSize, m_bRelative);
    case FSWCHR_ProcWrite:
	{
	    IHXBuffer* pBuffer;
	    HX_RESULT retVal;
	    
	    HX_ASSERT(m_pBuffer);

	    HX_RELEASE(m_pBuffer);
	    pBuffer = m_pBuffer;
	    m_pBuffer = NULL;
	    
	    retVal = m_pCurrentHandle->m_pFileObject->Write(pBuffer);
	    
	    pBuffer->Release();
	    
	    return retVal;
	}
    case FSWCHR_ProcAdvise:
	retVal = m_pCurrentHandle->m_pFileObject->Advise(m_ulSize);
	if (SUCCEEDED(retVal))
	{
	    if (m_ulSize == HX_FILEADVISE_SYNCACCESS)
	    {
		m_bSyncMode = TRUE;
	    }
	    else if (m_ulSize == HX_FILEADVISE_ASYNCACCESS)
	    {
		m_bSyncMode = FALSE;
	    }
	}
	m_State = FSWCHR_Ready;
	return retVal;
    default:
	// nothing to do
	break;
    }

    return HXR_UNEXPECTED;
}

/****************************************************************************
 *  ProcessRead
 */
HX_RESULT CFileSwitcher::ProcessRead(void)
{
    ULONG32 ulSize = m_ulSize - m_ulProcessedSize;
    m_ulChunkSize = (ulSize <= MAX_CHUNK_SIZE) ? 
		     ulSize : MAX_CHUNK_SIZE;

    return m_pCurrentHandle->m_pFileObject->Read(m_ulChunkSize);
}

/****************************************************************************
 *  ReadNextFragment
 */
HX_RESULT CFileSwitcher::ReadNextFragment(void)
{
    HX_RESULT retVal = HXR_FAIL;

    if ((!m_bClosing) &&
	m_pCurrentHandle &&
	m_pCurrentHandle->m_pFileObject)
    {
	if (m_bSyncMode ||
	    (m_ulFragmentCount < MAX_CONSECUTIVE_FRAGMENT_LOADS))
	{
	    retVal = ProcessRead();
	}
	else
	{
	    m_ulFragmentCount = 0;
	    retVal = m_pScheduler->RelativeEnter(this, 0);
	}
    }

    if (FAILED(retVal))
    {
	retVal = ReadDone(HXR_FAIL, NULL);
    }

    return retVal;
}

/****************************************************************************
 *  IHXFileSwitcher methods - Main interface
 */
/****************************************************************************
 *  Init
 */
STDMETHODIMP CFileSwitcher::Init(IHXFileObject* pFileObject,
				 ULONG32 ulFlags,
				 IHXFileResponse* pResponse,
				 IUnknown* pContext,
				 UINT16 uMaxChildCount)
{
    HX_RESULT retVal = HXR_OK;

    if (m_State != FSWCHR_Offline)
    {
	retVal = HXR_UNEXPECTED;
    }

    if (SUCCEEDED(retVal))
    {
	Reset();

	HX_ASSERT(pFileObject);
	HX_ASSERT(pResponse);
	HX_ASSERT(pContext);

	m_uMaxChildCount = uMaxChildCount;
	m_ulFlags = ulFlags;
    
	// First Entry in the table is used as RootHandle
	m_pHandleTable = new FileHandle[m_uMaxChildCount + 1];
	if (m_pHandleTable == NULL)
	{
	    retVal = HXR_OUTOFMEMORY;
	}
    }

    if (SUCCEEDED(retVal))
    {
	retVal = pContext->QueryInterface(
	    IID_IHXCommonClassFactory,
	    (void**) &m_pClassFactory);
    }

    if (SUCCEEDED(retVal))
    {
	retVal = pContext->QueryInterface(
	    IID_IHXScheduler, 
	    (void**) &m_pScheduler);
    }

    if (SUCCEEDED(retVal))
    {
	HX_ASSERT(!m_pResponse);

	m_pHandleTable = m_pHandleTable;
	m_pHandleTable->m_pFileObject = pFileObject;
	pFileObject->AddRef();

	m_State = FSWCHR_ProcInit;
	m_pResponse = pResponse;
	m_pResponse->AddRef();

	retVal = pFileObject->Init(m_ulFlags, (IHXFileResponse*) this);

	if (FAILED(retVal))
	{
	    retVal = HandleFailureSync(retVal);
	}
    }

    return retVal;
}

/****************************************************************************
 *  Read
 */
STDMETHODIMP CFileSwitcher::Read(ULONG32 ulSize,
				 IHXFileResponse* pResponse,
				 const char* pFileName)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if ((m_State == FSWCHR_Ready) && (!m_bClosing))
    {
	HX_ASSERT(!m_pResponse);

	m_ulSize = ulSize;
	m_pResponse = pResponse;
	m_pResponse->AddRef();

	m_State = FSWCHR_ProcRead;

	retVal = GetFileHandle(pFileName);
    }

    return retVal;	
}

/****************************************************************************
 *  Write
 */
STDMETHODIMP CFileSwitcher::Write(IHXBuffer* pBuffer,
				  IHXFileResponse* pResponse,
				  const char* pFileName)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if ((m_State == FSWCHR_Ready) && (!m_bClosing))
    {
	HX_ASSERT(!m_pResponse);
	HX_ASSERT(!m_pBuffer);

	m_pBuffer = pBuffer;
	m_pBuffer->AddRef();
	m_pResponse = pResponse;
	m_pResponse->AddRef();

	m_State = FSWCHR_ProcWrite;

	retVal = GetFileHandle(pFileName);
    }

    return retVal;
}

/****************************************************************************
 *  Seek
 */
STDMETHODIMP CFileSwitcher::Seek(ULONG32 ulOffset,
				 BOOL bRelative,
				 IHXFileResponse* pResponse,
				 const char* pFileName)
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if ((m_State == FSWCHR_Ready) && (!m_bClosing))
    {
	HX_ASSERT(!m_pResponse);

	m_ulSize = ulOffset;

⌨️ 快捷键说明

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