chxavsitesupplier.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 524 行

CPP
524
字号
/************************************************************************
 * chxavsitesupplier.cpp
 * ---------------------
 *
 * Synopsis:
 * Contains the implementation of the CHXAvSiteSupplier class.  This object 
 * will provide the mechanism by which the core can blit to the screen.
 *
 * Target:
 * Symbian OS
 *
 *
 * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 *****************************************************************************/

// Standard includes...

// Includes from Helix...
#include "hxcom.h"
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxwin.h"
#include "hxtick.h"
#include "ihxpckts.h"
#include "hxcomm.h"
#include "minisite.h"
#include "minisymbiansite.h"

// Includes from this project...
#include "chxavplayerui.h"
#include "chxavplayer.h"
#include "chxavplayviewwindow.h"
#include "hxsym_debug.h"
#include "chxavsitesupplier.h"



#define BORDER_WIDTH 1

// IUnknown implementation body...
BEGIN_INTERFACE_LIST(CHXAvSiteSupplier)
    INTERFACE_LIST_ENTRY(IID_IHXSiteSupplier, IHXSiteSupplier)
    END_INTERFACE_LIST


/* 
 * CHXAvSiteSupplier
 * -----------------
 * Ctor.
 *
 */
CHXAvSiteSupplier::CHXAvSiteSupplier() 
:
    m_classFactory(NULL),
    m_pContext(NULL),
    m_sitesManager(NULL),
    m_pDSA(NULL),
    m_pRenderWindow(0),
    m_bIsDSAStarted(false)
{
}




/*
 * ~CHXAvSiteSupplier
 * ------------------
 * Dtor.
 *
 */
CHXAvSiteSupplier::~CHXAvSiteSupplier()
{
    HX_DELETE(m_pDSA);
    HX_RELEASE(m_classFactory);
    HX_RELEASE(m_sitesManager);
    HX_RELEASE(m_pContext);

    HX_ASSERT(m_sitesCreated.IsEmpty());
    m_sitesCreated.RemoveAll();
}





/*
 * ConstructL
 * ----------
 *
 * constuct with IHXPlayer context
 *
 */
void 
CHXAvSiteSupplier::ConstructL(IUnknown* pContext, CCoeControl* pRenderWindow)
{
    HX_ASSERT(pContext);
    HX_ASSERT(pRenderWindow);
 
    m_pRenderWindow = pRenderWindow;
    m_pContext      = pContext;
    if( m_pContext )
    {
        m_pContext->AddRef();
        m_pContext->QueryInterface(IID_IHXSiteManager,(void**)&m_sitesManager);
        m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_classFactory);
        HX_ASSERT(m_sitesManager);
        HX_ASSERT(m_classFactory);
    }
}


//
// IHXSiteSupplier::SitesNeeded
//
// Called by player during setup of renderer sites during presentation
// layout (just after play request issued).
//
STDMETHODIMP
CHXAvSiteSupplier::SitesNeeded(UINT32 uRequestID, IHXValues *pProps)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::SitesNeeded()\n"));

    HXxWindow* pWin                     = NULL;
    HRESULT             hres            = HXR_OK;
    IHXValues*          pSiteProps      = NULL;
    IHXSiteWindowed*    pSiteWindowed   = NULL;
    IHXBuffer*          pValue          = NULL;
    UINT32              style           = 0;
    IHXSite*            pSite           = NULL;
    TInt                osErr           = KErrNone;
    IHXSite2*           pSite2          = NULL;
    
    HX_ASSERT(m_pRenderWindow);
    CCoeEnv* pCoeEnv  = m_pRenderWindow->ControlEnv();

    HX_ASSERT(pProps);
    

    //Only create one direct screen object and let all the sites share
    //it.
    if( NULL==m_pDSA )
    {
        TRAP(osErr, m_pDSA =
             CDirectScreenAccess::NewL( pCoeEnv->WsSession(),
                                        *pCoeEnv->ScreenDevice(),
                                        *(m_pRenderWindow->DrawableWindow()),
                                        *this
                                        ));
        StartDSA(); 
    }
    

    hres = HXR_FAIL;
    if(SUCCEEDED(m_classFactory->CreateInstance(CLSID_IHXSiteWindowed,
                                                (void**)&pSiteWindowed)))
        if(SUCCEEDED(pSiteWindowed->QueryInterface(IID_IHXSite,
                                                   (void**)&pSite)))
            hres = pSiteWindowed->QueryInterface(IID_IHXValues,
                                                 (void**)&pSiteProps);

    if (!pProps)
        hres =  HXR_INVALID_PARAMETER;
    
    if (HXR_OK != hres)
    {
        goto exit;
    }


    //We need to figure out what type of site we are supposed to
    //create. We need to "switch" between site user and site
    //properties. So look for the well known site user properties that
    //are mapped onto sites...
    if( SUCCEEDED(pProps->GetPropertyCString("playto",pValue)))
    {
        pSiteProps->SetPropertyCString("channel",pValue);
        HX_RELEASE(pValue);
    }
    else
    {
        if(SUCCEEDED(pProps->GetPropertyCString("name",pValue)))
        {
            pSiteProps->SetPropertyCString("LayoutGroup",pValue);
            HX_RELEASE(pValue);
        }
    }
        
    /*
     * We need to wait until we have set all the properties before
     * we add the site.
     */
    HX_ASSERT(m_sitesManager);
    hres = m_sitesManager->AddSite(pSite);
    if (HXR_OK == hres)
    {
        //Add ourselves as a site watcher..
        pSite->QueryInterface(IID_IHXSite2, (void**)&pSite2 );
        if( pSite2 )
        {
            pSite2->AddPassiveSiteWatcher(this);
            HX_RELEASE(pSite2);
        }
        

        //We only attach a real window to the first site created.
        pWin = new HXxWindow();
        memset( pWin, 0, sizeof(HXxWindow));
        
        pWin->window = m_pRenderWindow->DrawableWindow();
        pWin->iDSA   = m_pDSA;
        
        // Set the clip rect one pixel small all around...
        TRect rect = m_pRenderWindow->Rect();
        pWin->x = 0;
        pWin->y = 0;
        pWin->height = rect.Height();
        pWin->width  = rect.Width();
        
        pWin->clipRect.left   = pWin->clipRect.top = BORDER_WIDTH;
        pWin->clipRect.bottom = pWin->height - BORDER_WIDTH;
        pWin->clipRect.right  = pWin->width - BORDER_WIDTH;
        
        pSiteWindowed->AttachWindow(pWin);

        pSite->AddRef();
        m_sitesCreated.SetAt(uRequestID, pSite);

        DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::SitesNeeded(): added site; now %ld sites\n", m_sitesCreated.GetCount()));

    }
    
exit:
    if (HXR_OK != hres)
    {
        if( m_pDSA )
            m_pDSA->Cancel();
        HX_DELETE(m_pDSA);
        HX_DELETE(pWin);
    }

    HX_RELEASE(pSiteProps);
    HX_RELEASE(pSiteWindowed);
    HX_RELEASE(pSite);

    return hres;
}

//
// IHXSiteSupplier::SitesNotNeeded
//
// Called when most recent presentation layout is being closed. This is not
// called after IHXPlayer::Stop(). The layout remains persistent until:
//  a) a new play request is issued (even if for exact same url, i.e., replay)
//  b) the player object is closed
//
STDMETHODIMP CHXAvSiteSupplier::SitesNotNeeded(UINT32 uRequestID)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::SitesNotNeeded()\n"));
    IHXSite*         pSite         = NULL;
    IHXSiteWindowed* pSiteWindowed = NULL;
    IHXSite2*        pSite2        = NULL;
    
    void *pVoid = NULL;

    if (!m_sitesCreated.Lookup(uRequestID, pVoid))
    {
        return HXR_INVALID_PARAMETER;
    }

    pSite = (IHXSite*)pVoid;
    m_sitesManager->RemoveSite(pSite);

    //Remove ourselves as a passive site watcher..
    pSite->QueryInterface(IID_IHXSite2, (void**)&pSite2 );
    if( pSite2 )
    {
        pSite2->AddPassiveSiteWatcher( (IHXPassiveSiteWatcher*)this);
        HX_RELEASE(pSite2);
    }
    

    // Need to actually do the work on destroying the window
    // and all that jazz.
    pSite->QueryInterface(IID_IHXSiteWindowed,(void**)&pSiteWindowed);

    //Free the window we passed in.
    HXxWindow* pWin = pSiteWindowed->GetWindow();
    pSiteWindowed->Destroy();
    HX_DELETE(pWin);

    HX_RELEASE(pSiteWindowed);

    m_sitesCreated.Remove(uRequestID);
    HX_RELEASE(pSite);

    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::SitesNotNeeded(): removed site; now %ld sites\n", m_sitesCreated.GetCount()));

    //If we have no more sites then destroy the direct screen access

    //object so it isn't associated with the playback window that is
    //not around anymore.
    if( m_sitesCreated.IsEmpty())
    {
        m_pDSA->Cancel();
        HX_DELETE(m_pDSA);
    }
    
    return HXR_OK;
}


//
// IHXSiteSupplier::BeginChangeLayout
//
// Called:
//  a) during layout cleanup done when renderers are closed. SitesNotNeeded() is called after this.
//  b) during first presentation layout
//
STDMETHODIMP
CHXAvSiteSupplier::BeginChangeLayout()
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::BeginChangeLayout()\n"));
    return HXR_OK;
}

//
// IHXSiteSupplier::DoneChangeLayout
//
// Called after SitesNeeded(), after layout is complete.
//
STDMETHODIMP
CHXAvSiteSupplier::DoneChangeLayout()
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::DoneChangeLayout()\n"));
    return HXR_OK;
}

bool CHXAvSiteSupplier::IsUsingSites() const
{
    return !m_sitesCreated.IsEmpty();
}


TInt CHXAvSiteSupplier::StartDSA()
{
    HX_ASSERT(m_pDSA);
    TRAPD(err, m_pDSA->StartL());
    //HX_ASSERT(KErrNone == err); // err expected when app looses foreground
    m_bIsDSAStarted = (err == KErrNone);
    return err;
}
 


//
// AbortNow() and Restart() are (always?) called in pairs. These are called when
// our render window is covered/uncovered, i.e., whenever we need to recalculate
// our clipping rect. This includes following cases:
//  a) menu goes up
//  b) dialog goes up
//  c) CCoeControl associated with DSA is destroyed
//  d) user presses app switcher key (before fg event)
//
// StartL() will fail in cases (c) and (d)
//
void CHXAvSiteSupplier::Restart(RDirectScreenAccess::TTerminationReasons aReason)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::Restart(): reason = %d\n", aReason));
    StartDSA();
}

void CHXAvSiteSupplier::AbortNow(RDirectScreenAccess::TTerminationReasons aReason)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::AbortNow(): reason = %d\n", aReason));
    m_pDSA->Cancel();
    m_bIsDSAStarted = false;
}


HX_RESULT CHXAvSiteSupplier::PositionChanged (HXxPoint* pPoint)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::PositionChanged() %d, %d\n", pPoint->x, pPoint->y));
    return HXR_OK;
}

namespace
{
HXxRect GetRect(IHXSite* pSite)
{
    HX_ASSERT(pSite);
    HXxSize size;
    pSite->GetSize(size);
    HXxPoint tl;
    pSite->GetPosition(tl);

    HXxRect rect;
    rect.left = tl.x;
    rect.top = tl.y;
    rect.right = rect.left + size.cx;
    rect.bottom = rect.top + size.cy;

    return rect;

}
}

void CHXAvSiteSupplier::RedrawAllSites()
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::RedrawAllSites()\n"));
    
    if( m_pDSA )
    {
        if( !m_bIsDSAStarted )
        {
            StartDSA();
        }

        if( m_bIsDSAStarted )
        {
            //Grab a sitemanager2 interface from our only player so we can
            //iterate over the sites.
            IHXClientEngine* pEngine       = NULL; 
            IUnknown*        pUnknown      = NULL;
            IHXSiteManager2* pSiteManager2 = NULL;
            IHXSite*         pSite         = NULL;
            ULONG32          nNumSites     = 0;
            
            m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine);
            HX_ASSERT(pEngine);
    
            if(pEngine)
            {
                //We should always have only 1 engine in the symbian players.
                int nPlayerCount = pEngine->GetPlayerCount();
                HX_ASSERT(nPlayerCount==1);
                if( nPlayerCount>0)
                {
                    pEngine->GetPlayer(0, pUnknown);
                    if(pUnknown)
                    {
                        pUnknown->QueryInterface(IID_IHXSiteManager2, (void**) &pSiteManager2);
                        if (pSiteManager2)
                        {
                            pSiteManager2->GetNumberOfSites(nNumSites);
                            for(unsigned int idx = 0; idx< nNumSites; idx++)
                            {
                                IHXSiteControl* pSiteController = NULL;
                                pSiteManager2->GetSiteAt(idx, pSite);
                                pSite->QueryInterface(IID_IHXSiteControl, (void**)&pSiteController);
                                if( pSiteController )
                                {
                                    //We want to do the recursive redraw. 
                                    pSiteController->ForceRedrawAll();
                                }
                                else
                                {
                                    //If we don't have tne new
                                    //interface, try doing it the old
                                    //non recursive way.
                                    pSite->DamageRect(GetRect(pSite));
                                    pSite->ForceRedraw();
                                }
                                HX_RELEASE(pSiteController);
                            }
                            HX_RELEASE(pSiteManager2);
                        }
                        HX_RELEASE(pUnknown);
                    }
                }
                HX_RELEASE(pEngine);
            }
        }
    }
}

void CHXAvSiteSupplier::RestackSites()
{
    HXxPoint point = {0,0};
    HXxSize  size = {0,0};
    TInt     nTotalHeight= 0;

    //Get our windows width and height
    TRect rect = m_pRenderWindow->Rect();

    //The site takes care of any scaling that needs to be done.  The
    //site supplier will take care of centering the site(s). First go
    //through all the sites and get the total height.
    CHXMapLongToObj::Iterator end = m_sitesCreated.End();
    CHXMapLongToObj::Iterator it = m_sitesCreated.Begin();
    for( ; it != end; ++it)
    {
        // First one created gets put on top...
        IHXSite* pSite = (IHXSite*)*it;
        pSite->GetSize(size);
        nTotalHeight  += size.cy;
    }
    
    //Now go through and restack and position sites.
    point.y = (rect.Height()-nTotalHeight)/2;
    if( point.y < 0 )
        point.y = 0;
    
    end = m_sitesCreated.End();
    for(it = m_sitesCreated.Begin(); it != end; ++it)
    {
        // First one created gets put on top...
        IHXSite* pSite = (IHXSite*)*it;
        pSite->GetSize(size);
        point.x = (rect.Width()-size.cx)/2;
        pSite->SetPosition(point);
        point.y += size.cy;     
    }
}

HX_RESULT CHXAvSiteSupplier::SizeChanged( HXxSize* pSize)
{
    DPRINTF(SYMP_INFO, ("CHXAvSiteSupplier::SizeChanged()\n"));
    RestackSites();
    return HXR_OK;
}

⌨️ 快捷键说明

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