hxpluginmanager.cpp

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

CPP
1,193
字号
/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: hxpluginmanager.cpp,v 1.2.2.2 2004/07/09 02:07:27 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (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.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * 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 "hxtypes.h"
#include "hxassert.h"
#include "debug.h"
#include "hxcom.h"
#include "hxccf.h"      // IHXCommonClassFactory
#include "ihxpckts.h"   // IHXBuffer
#include "hxplugn.h"    // IHXComponentPlugin
#include "hxprefs.h"	// IHXPreferences
#include "hxprefutil.h"
#include "findfile.h"
#include "chxpckts.h"   // CHXHeader
#include "dllacces.h"
#include "dllpath.h"
#include "pathutil.h"
#include "hxver.h"

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

#if defined(_STATICALLY_LINKED)
#include "staticff.h"
#endif

#include "hxpluginarchive.h"
#include "hxplugindll.h"
#include "hxplugin.h"
#include "hxpluginmanager.h"


#if(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;
}
#endif


IMPLEMENT_COM_CREATE_FUNCS( HXPluginManager )

BEGIN_INTERFACE_LIST_NOCREATE( HXPluginManager )
    INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginEnumerator )
    INTERFACE_LIST_ENTRY_SIMPLE( IHXPlugin2Handler )
    INTERFACE_LIST_ENTRY_SIMPLE( IHXPluginHandler3 )
END_INTERFACE_LIST

HXPluginManager::HXPluginManager() 
: m_pContext(0)
, m_pClassFactory(0)
{
}

HXPluginManager::~HXPluginManager()
{
    Close();
}

STDMETHODIMP HXPluginManager::Init(IUnknown* pContext)
{
    DPRINTF(D_INFO, ("HXPluginManager::Init()\n"));
    HX_RESULT result = HXR_FAIL;

    if( SUCCEEDED( result = RegisterContext( pContext ) ) )
    {
	result = ReadFromRegistry();
    }

    return result;
}


STDMETHODIMP_(ULONG32) HXPluginManager::GetNumOfPlugins2()
{
    return m_plugins.GetCount();
}


STDMETHODIMP
HXPluginManager::GetPluginInfo(UINT32 unIndex, REF(IHXValues*) /*OUT*/ pValues)
{
    return HXR_NOTIMPL;
}

///////////////////////////////////////////////////////////////////////////////
//
HX_RESULT HXPluginManager::ReloadPluginsNoPropagate()
{
    return ReloadPlugins();
}

///////////////////////////////////////////////////////////////////////////////
//
HX_RESULT HXPluginManager::ReloadPlugins()
{
    DPRINTF(D_INFO, ("HXPluginManager()::ReloadPlugins()\n"));

    HX_RESULT result = HXR_OK;

    // reload plugins for all mountpoints
    for(CHXMapStringToString::Iterator iter = m_mountPoints.Begin(); iter != m_mountPoints.End(); ++iter)
    {
	const char* pMountPoint = (const char*) *iter;
	if( FAILED( ReloadPlugins( pMountPoint ) ) )
	{
	    result = HXR_FAIL;
	}
    }

    return result;
}

/////////////////////////////////
//
// do we already have the given dll in our collection?
//
// we use case insensitive match in all OS/filesystem cases (even if technically inappropriate)
//
bool HXPluginManager::DoesDLLExist(const char* pszName, const char* pszMountPoint)
{
    CHXSimpleList::Iterator iter;
    for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
    {
	HXPluginDLL* pLib = (HXPluginDLL*) *iter;

        if( !pLib->GetFileName().CompareNoCase(pszName) && !pLib->GetMountPoint().CompareNoCase(pszMountPoint) )
        {
            DPRINTF(D_INFO, ("HXPluginManager::DoesDLLExist(): plugin dll exists '%s'\n", (const char*)pLib->GetFileName()));
            return true;
        }
    }

    for(iter = m_otherDlls.Begin(); iter != m_otherDlls.End(); ++iter)
    {
	HXOtherDLL* pLib = (HXOtherDLL*) *iter;
        if( !pLib->GetFileName().CompareNoCase(pszName) && !pLib->GetMountPoint().CompareNoCase(pszMountPoint) )
        {
            DPRINTF(D_INFO, ("HXPluginManager::DoesDLLExist(): other dll exists '%s'\n", (const char*)pLib->GetFileName()));
            return true;
        }
    }
    return false;
}

HX_RESULT HXPluginManager::SaveToArchive(const char* pszArchiveFile)
{
    DPRINTF(D_INFO, ("SaveToArchive(): writing '%s' (%d plugin dlls; %d other dlls)\n", pszArchiveFile, m_pluginDlls.GetCount(), m_otherDlls.GetCount()));
    HXPluginArchiveWriter ar;
    HX_RESULT hr = ar.Open(m_pContext, pszArchiveFile);
    if(SUCCEEDED(hr))
    {
        CHXSimpleList::Iterator iter;
        for(iter = m_pluginDlls.Begin(); iter != m_pluginDlls.End(); ++iter)
        {
            HXPluginDLL* pLib = (HXPluginDLL*) *iter;
            pLib->Archive(ar);
        }
        for(iter = m_otherDlls.Begin(); iter != m_otherDlls.End(); ++iter)
        {
            HXOtherDLL* pLib = (HXOtherDLL*) *iter;
            pLib->Archive(ar);
        }
    }
    ar.Close();
    return hr;
}

HX_RESULT HXPluginManager::LoadPluginDLLFromArchive(const char* pszMountPoint, HXPluginArchiveReader& ar)
{
    HXPluginDLL* pPluginDLL = new HXPluginDLL(m_pContext, pszMountPoint, ar);
    if( !pPluginDLL )
    {
        return HXR_OUTOFMEMORY;
    }
    pPluginDLL->AddRef();

    HX_ASSERT(!DoesDLLExist(pPluginDLL->GetFileName(), pPluginDLL->GetMountPoint()));

    // no need to load! that's the point of the archive
    HX_ASSERT(pPluginDLL->GetNumPlugins() > 0);

    m_pluginDlls.AddTail(pPluginDLL);

    return HXR_OK;
}

HX_RESULT HXPluginManager::LoadOtherDLLFromArchive(const char* pszMountPoint, HXPluginArchiveReader& ar)
{
    HXOtherDLL* pOtherDLL = new HXOtherDLL(pszMountPoint, ar);
    if( !pOtherDLL )
    {
        return HXR_OUTOFMEMORY;
    }

    pOtherDLL->AddRef();
    HX_ASSERT(!DoesDLLExist(pOtherDLL->GetFileName(), pOtherDLL->GetMountPoint()));
    m_otherDlls.AddTail(pOtherDLL);

    return HXR_OK;
}

//
// Try to re-construct plugin dll and associated plugin objects
// from saved archive for faster plugin discovery
//
// If you want to override this (i.e., after new dlls installed), delete the archive
//
HX_RESULT HXPluginManager::LoadFromArchive(const char* pszArchiveFile, const char* pszMountPoint)
{
    DPRINTF(D_INFO, ("LoadFromArchive(): looking for '%s'\n", pszArchiveFile));
    HXPluginArchiveReader ar;
    HX_RESULT hr = ar.Open(m_pContext, pszArchiveFile);
    if(SUCCEEDED(hr))
    {
        while(SUCCEEDED(hr) && !ar.AtEnd())
        {
            UINT32 type;
            ar.Read(type);
            switch(type)
            {
            case ARCHIVE_ID_PLUGIN_DLL:
                hr = LoadPluginDLLFromArchive(pszMountPoint,ar);
                break;
            case ARCHIVE_ID_OTHER_DLL:
                hr = LoadOtherDLLFromArchive(pszMountPoint, ar);
                break;
            default:
                hr = HXR_FAIL;
                break;
            }
        }
    
        ar.Close();

        DPRINTF(D_INFO, ("LoadFromArchive(): found %ld plugin dlls, %ld other dlls\n", m_pluginDlls.GetCount(), m_otherDlls.GetCount()));
    }
    else
    {
        DPRINTF(D_INFO, ("LoadFromArchive(): archive missing\n"));
    }

    return hr;
}

///////////////////////////////////////////////////////////////////////////////
//
// 'query plugin dlls'
//
// load all plugin dlls and determine associated plugin attributes
//
// called when:
//
//   1) a mount point is added
//   2) a mount point is removed and re-added (e.g., dynamic re-load)
//
// does nothing if dlls for mount point have already been loaded and queried
//
HX_RESULT HXPluginManager::ReloadPluginsWithFindFile(
               const char* pMountPoint, CFindFile* pFileFinder,
               IHXBuffer* pPathBuffer, const char* pszPluginDir)
{
    DPRINTF(D_INFO, ("HXPluginManager()::ReloadPluginsWithFindFile()\n"));
  
    CHXString strArchiveFile;
    IHXPreferences* pPrefs = 0;
    m_pContext->QueryInterface(IID_IHXPreferences, (void**) &pPrefs);
    HX_RESULT hr = ReadPrefCSTRING(pPrefs, "PluginArchiveFileName", strArchiveFile);
    HX_RELEASE(pPrefs);
    if(SUCCEEDED(hr))
    {
        // first try to recreate dll and plugin state from archive
        hr = LoadFromArchive(strArchiveFile, pMountPoint); 
    }
    if(HXR_OUTOFMEMORY == hr)
    {
        return hr;
    }
    
    // iterate files in this plugin directory
    hr = HXR_OK;
    bool bWriteArchive = false;
    const char* pszDllName = pFileFinder->FindFirst();
    for (; pszDllName; pszDllName = pFileFinder->FindNext())
    {
        if( DoesDLLExist(pszDllName, pMountPoint) )
        {
            // we already have info about this dll (perhaps from achive)
            continue;
        }

        // since we found a dll we don't know about yet we need to update the archive
        bWriteArchive = true;

        // create plugin dll wrapper, assuming this is a plugin dll
        HXPluginDLL* pPluginDll  = new HXPluginDLL(m_pContext, pszDllName, pMountPoint);
        if(!pPluginDll)
        {
            // oom
	    hr = HXR_OUTOFMEMORY;
            break;
        }
        pPluginDll->AddRef();

        // load dll to force query of supported plugins
        hr = pPluginDll->Load();
        if (SUCCEEDED(hr))
        {
            // add successfully loaded dll to list
            pPluginDll->AddRef();
            m_pluginDlls.AddTail(pPluginDll);

            // Unload the dll. The dll was loaded only to query supported plugin 
            // info. It will be re-loaded only when actually needed, i.e., when
            // an instance of a plugin that it implements is requested.
            pPluginDll->Unload();
        }
        HX_RELEASE(pPluginDll);
        if (FAILED(hr))
        {
            if(HXR_OUTOFMEMORY == hr)
            {
                break;
            }

            // lib load attempt failed; add this to 'other' dll list (maybe it is a codec dll, e.g.)
            HXOtherDLL* pOtherDll  = new HXOtherDLL(pszDllName, pMountPoint);
            if( !pOtherDll)
            {
                //oom
                hr = HXR_OUTOFMEMORY;
                break;
            }

⌨️ 快捷键说明

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