chxavplayview.cpp

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

CPP
1,708
字号
/************************************************************************
 * chxavplayview.cpp
 * -----------------
 *
 * Synopsis:
 * Contains the implementation of the CHXAvPlayView class.  This class 
 * will control actual playback once a file/url has been selected for play.
 *
 * Target:
 * Symbian OS
 *
 *
 * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
 *
 ************************************************************************/

// Symbian includes...
#include <coeccntx.h>
#include <eikbtgpc.h>
#include <eikmenub.h>
#include <eikmenup.h>
#include <eikfutil.h>
#include <eikenv.h>
#include <eikappui.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <avkon.hrh>
#include <avkon.rsg>
#include <eikmenup.h>
#include <eikon.hrh>
#include <aknviewappui.h>
#include <apchangeobserver.h>

// Helix includes...
#include "hxassert.h"
#include "ihxpckts.h"
#include "hxstring.h"
#include "hxurl.h"

// Includes for this project...
#include "hxsym_debug.h"
#include "realplayer.rsg"
#include "realplayer.mbg"
#include "chxavplayer.h"
#include "chxavplayerui.h"
#include "chxavfilestore.h"
#include "chxavfileui.h"
#include "chxavclipinfolist.h"
#include "chxavconfignames.h"
#include "chxavinfolistpopup.h"
#include "chxavcleanupstack.h"
#include "chxavnavipanecontrol.h"
#include "chxavplaylistnavicontrol.h"
#include "chxavplayviewwindow.h"
#include "chxavplayerstate.h"
#include "chxavviewbase.h"
#include "chxavplayview.h"
#include "hxapihelp.h"
#include "hxsym_leaveutil.h"
#include "chxavcleanstring.h"
#include "realplayer.hrh"
#include "chxavnetconnectui.h"
#include "chxavplayerr.h"


namespace
{
    // how long to show non-default navi control after user action
    const TUint k_msShowTempNavi = 1000;
    
    // how often to reset inactivity timer so backlight stays on during a video presentation
    const TUint k_msBacklightInterval = 5000;
}


/* 
 * CHXAvPlayView
 * -------------
 * Constructor.
 *
 */
CHXAvPlayView::CHXAvPlayView(TInt viewIndex, CHXAvPlayerUI *playerUI)
: CHXAvViewBase(viewIndex, playerUI)
, m_bViewPlaylistMode(false)
, m_bEnsureResumeOnExitPlaylistMode(false)
, m_lastPhoneState(ESACallNone)
, m_msSeekStep(0)
, m_bShutDownOnViewDeactivate(true)
{
}



/*
 * ~CHXAvPlayView
 * --------------
 * Destructor.
 *
 */
CHXAvPlayView::~CHXAvPlayView()
{
    // player may not be shutdown yet (e.g., exiting from 'child' view)
    HX_ASSERT(m_player);
    if( m_player )
    {
        m_player->ShutDown();
        m_player->GetPlayerState().RemoveObserver(this);
    }

}



/* 
 * ConstructL
 * ----------
 * Construction of elements.
 *
 */
void CHXAvPlayView::ConstructL()
{
    BaseConstructL(R_AVP_PLAYER_VIEW_INFO);

    // timer for hiding volume control after user interaction delay 
    const CHXAvCommand& cmdHide = 
	MakeCommand(this, &CHXAvPlayView::HideTempNaviControlNowL);
    m_cbTempNaviDisplay.ConstructL(cmdHide);

    // timer for periodically resetting backlight so it stays on while playing
    const CHXAvCommand& cmdBacklight = 
	MakeCommand(this, &CHXAvPlayView::OnBacklightTimer);
    m_cbBacklight.ConstructL(cmdBacklight);


    // see SetEndSeekCallback()
    const CHXAvCommand& cmdEndSeek = MakeCommand(this, &CHXAvPlayView::OnEndSeekCallback);
    m_cbEndSeek.ConstructL(cmdEndSeek);

   
    // watch for phone call events
    const CHXAvCommand& cmdOnPhoneEvent = 
        MakeCommand(this, &CHXAvPlayView::OnPhoneEvent);
    m_saWatcher.ConstructL(KUidCurrentCall, CActive::EPriorityHigh);

    m_lastPhoneState = m_saWatcher.GetSa().GetState(KUidCurrentCall);
    DPRINTF(SYMP_INFO, ("CHXAvPlayView::ContructL(): current phone state = %ld\n", m_lastPhoneState));

    m_saWatcher.SetEventActionL(cmdOnPhoneEvent);
    m_saWatcher.StartWatching();


    // command to execute if user cancels while connecting
    const CHXAvCommand& cmdCancelConnect =
        MakeCommand(this, &CHXAvPlayView::OnUserCancelConnect);

    m_spNetConnectUi = new (ELeave) CHXAvNetConnectUI();
    m_spNetConnectUi->ConstructL(m_playerUI->GetClientEngineManager()->GetEngine(), cmdCancelConnect);

    m_player = new (ELeave) CHXAvPlayer();
    m_player->ConstructL(m_playerUI->GetClientEngineManager(), m_spNetConnectUi);
}


////////////////////////////////////////
//
void
CHXAvPlayView::HandleVolumeCommand(TInt idCmd)
{
    switch(idCmd)
    {
    case EVolUp:
        m_player->StepVolume(1);
        if( m_player->IsMuted())
        {
            // unmute 
            m_player->Mute(false);  
        }
        
	break;
    case EVolDown:
        m_player->StepVolume(-1);
        if( m_player->GetVolume() == 0 )
        {
            // ensure mute
            m_player->Mute(true);
        }
        else
        {
            // ensure not muted after user volume change to (still) positive volume level
            m_player->Mute(false);
        }
        break;
    default:
        HX_ASSERT(false);
	break;
    }
}

////////////////////////////////////////////////
//
void CHXAvPlayView::DoExitPlaylistModeL(bool bPlayCurrent)
{
    m_bViewPlaylistMode = false;
    DeactivateNaviPlaylistControl();
    if(bPlayCurrent && m_player->CanResume() )
    {
        m_player->PlayCurrent();
    }
    else
    {
        UpdateSoftkeyMenuStateL();
    }
}

////////////////////////////////////////////////
// activate navi playlist control with auto-hide timer ON so
// it hides after a brief display
void CHXAvPlayView::ShowTempPlaylistControlL()
{
    if(!m_bViewPlaylistMode)
    {
        ActivateNaviPlaylistControlL(k_msShowTempNavi);
        m_naviPane->PushL(*m_spNaviPlaylistDecorator);
    }
}


////////////////////////////////////////////////
//
// check for playlist-related commands
//
// return 'false' if we should continuing handling command
//
bool CHXAvPlayView::TryHandlePlaylistCommandL(TInt command)
{
    bool bWasHandled = true;

    if(m_player->IsPlaylistLoaded() && m_player->GetPlaylistItemCount() > 1 )
    {
        switch(command)
        {
            case EShowPlaylistInfo:
                HX_ASSERT(!m_bViewPlaylistMode);
                ShowTempPlaylistControlL();
                break;
            case EEnterPlaylistMode:
                //HX_ASSERT(!m_bViewPlaylistMode);
                if( !m_bViewPlaylistMode )
                {
                    m_bEnsureResumeOnExitPlaylistMode = m_player->IsPlaying();
                    m_bViewPlaylistMode = true;
                    UpdateSoftkeyMenuStateL();
                    
                    // activate navi playlist control with auto-hide timer OFF
                    ActivateNaviPlaylistControlL(0);
                    m_naviPane->PushL(*m_spNaviPlaylistDecorator);
                }
                break;
            case EExitPlaylistMode:
                HX_ASSERT(m_bViewPlaylistMode);
                if( m_bViewPlaylistMode)
                {
                    DoExitPlaylistModeL(m_bEnsureResumeOnExitPlaylistMode);
                    
                }
                break;
            case ENextClip:
                m_player->AdvancePlaylist(CHXAvPlayer::advanceNext | CHXAvPlayer::advanceLoop);
                ShowTempPlaylistControlL();
                if(!m_bViewPlaylistMode && m_player->CanResume())
                {
                    m_player->PlayCurrent();
                }
	        break;
            case EPrevClip:
                m_player->AdvancePlaylist(CHXAvPlayer::advancePrev | CHXAvPlayer::advanceLoop);
                ShowTempPlaylistControlL();
                if(!m_bViewPlaylistMode && m_player->CanResume())
                {
                    m_player->PlayCurrent();
                }
	        break;
            case EShowDefaultMenu:
                DoExitPlaylistModeL(false);
                HandleShowPopupL();
                break;

            default:
                bWasHandled = false;
                break;
        }
    }
    else
    {
        switch(command)
        {
            // ignore these when playlist not loaded
            case EShowPlaylistInfo:
            case EEnterPlaylistMode:
            case EExitPlaylistMode:
            case ENextClip:
            case EPrevClip:
                break;
            default:
                bWasHandled = false;
                break;
        }
    }
 
    return bWasHandled;
}

void CHXAvPlayView::DoTogglePlayState()
{
    if (m_player->IsPaused())
    {
	m_player->Resume();
    }
    else if (m_player->IsStopped())
    {
	m_player->PlayCurrent();
    }
    else
    {
	m_player->Pause();
    }
}

/*
 * HandleSeekKeyCommand
 * --------------------
 * User pressed seek forward/back key.
 *
 */
void 
CHXAvPlayView::HandleSeekKeyCommand(bool bForward)
{
    DPRINTF(SYMP_INFO, ("CHXAvPlayView::HandleSeekKeyCommand('%s')\n", dbg::Bool(bForward)));
    if (m_player->IsSeeking())
    {
	HX_ASSERT(!m_player->GetClipInfo().IsLive());

	UINT32 newTime = m_player->GetClipTime();
 
	m_msSeekStep = GetNextSeekStep(m_msSeekStep);

	if( bForward )
	{
	    // ok if we go past duration -- player handles it by moving to next clip (or stopping)
	    newTime += m_msSeekStep;
	}
	else
	{
	    newTime = m_player->GetClipTime();
	    if( newTime > m_msSeekStep )
	    {
		newTime -= m_msSeekStep;
	    }
	    else
	    {
		newTime = 0;
	    }
	}

	m_player->SetSeekPoint(newTime);
    }
}
////////////////////////////////////////
//
void CHXAvPlayView::DoViewClipInfoL()
{
    CHXAvClipInfoList* pList = new (ELeave) CHXAvClipInfoList();
    AUTO_PUSH_POP(pList);
    pList->ConstructL();
    pList->BuildClipInfoL(m_player);

    CHXAvInfoListPopup* pPopup = new (ELeave) CHXAvInfoListPopup();

    // save cleanupstack init until LD
    {
        AUTO_PUSH_POP(pPopup);
        pPopup->ConstructL( CHXAvCleanString(R_AVP_CLIPINF_TITLE)(), pList);
    }

    pPopup->ExecuteLD();
}

////////////////////////////////////////
//
void
CHXAvPlayView::DoSaveL()
{

    //
    // perform action based on type of URL:
    //
    // local ram url  -> copy ram file
    // local rm url   -> copy file
    // network url    -> create link
    //

    CHXString strSource;

    bool bUserCancelled = false;
    bool bSavingPlaylist = false;

    // save playlist or current clip that is playing?
    if( m_player->IsPlaylistLoaded() &&  m_player->GetPlaylistItemCount() > 1)
    {
        // query user: playlist or current clip
        TInt idxSel = 0;
        CAknListQueryDialog* pDlg = new (ELeave) CAknListQueryDialog(&idxSel);

        TInt ret = pDlg->ExecuteLD(R_AVP_SELECT_SAVE_SOURCE_DLG);
        if(ret != 0)
        {
            //HX_ASSERT((ret == EAknSoftkeyOk) || (ret == EAknSoftkeyYes));
            bool bCopyRam = (idxSel == 0);
            if( bCopyRam )
            {
                // save playlist (ram)
                bSavingPlaylist = true;
                strSource = m_player->GetMainURL();
            }
        }
        else
        {
            bUserCancelled = true;
        }
    }

    if(!bUserCancelled)
    {
   
        const CHXAvVector<CHXAvMediaFolderInfoPtr>& storeInfo = m_playerUI->GetMediaStoreInfoL();

        // XXXLCM automatic smart pointer not cleanup stack safe

        // set an arbitrary 'current path' for the file store
        CHXAvFileStorePtr spStore = new (ELeave) CHXAvFileStore();
        spStore->ConstructL(storeInfo[0]->GetRoot());

        CHXAvFileUIPtr spFileUi = new (ELeave) CHXAvFileUI();
        spFileUi->ConstructL(m_playerUI, spStore);

        if(strSource.IsEmpty())
        {
            // set source file to current URL
            strSource = m_player->GetPlayURL(); 
        }

        HX_ASSERT(!strSource.IsEmpty());
        CHXAvCleanString urlText(strSource);
        
        if( CHXAvUtil::IsLocal(urlText()))
        {
            //
            // copy file
            //

            // use source filename for default name

	    // url may be escaped; get unescaped path-only portion 
            // (e.g., \realnetworks\root\foo.rm)
	    HBufC* pSrcPath = CHXAvUtil::AllocStdPathFromPlayerUrlL(urlText()); 
	    AUTO_PUSH_POP_DEL(pSrcPath);

            bool bIsValidLocalPath = CHXAvFile::PathExists(*pSrcPath);
            HX_ASSERT(bIsValidLocalPath); // menu item should be hidden to prevent this
            if( bIsValidLocalPath )
            {
                if( bSavingPlaylist )
                {
	            spFileUi->DoSavePlaylistL(*pSrcPath, KNullDesC);
                }
                else
                {
                
                    spFileUi->DoSaveClipL(*pSrcPath, KNullDesC);
                }
            }
        }
        else
        {
            //
            // create link
            //

            // set default link name to clip display title
            HBufC* pTitleText = CHXAvMisc::AllocTitleL(m_player);
            if(pTitleText)
            {
                AUTO_PUSH_POP_DEL(pTitleText);
                spFileUi->DoCreateLinkL(strSource, *pTitleText);
            }
            else
            {
                spFileUi->DoCreateLinkL(strSource, KNullDesC);
            }
	    
        }
    }

}


////////////////////////////////////////////////         
// we want to delay a bit (i.e., after the last seek key press)
// before telling  the player to end seeking (and resume play at
// new point);
//
// this allows for a user entering a series of quick key presses and
// avoids excessive start and end seek commands
//
void CHXAvPlayView::SetEndSeekCallback(bool bEnable)
{
    if(bEnable && m_player->IsSeeking())
    {
        const TUint32 k_msEndSeekDelay = 400;
	m_cbEndSeek.Set(k_msEndSeekDelay);
    }
    else
    {
	m_cbEndSeek.Stop();
    }
}
////////////////////////////////////////////////         
// see SetEndSeekCallback()
void CHXAvPlayView::OnEndSeekCallback()
{
    // only call end seek if we are still in seek mode; it is possible that 
    // state changed (e.g., stop requested) since we set the end seek callback
    if( m_player->IsSeeking() )
    {
        m_player->EndSeek();
    }
}

/*
 * EnterSeekMode
 * -------------
 * Start and end seek.
 *
 */
void 
CHXAvPlayView::EnterSeekMode(bool bEnter)
{
    if (bEnter)
    {
        m_msSeekStep = 0; 

        SetEndSeekCallback(false);
        // player may be seeking in case where end seek callback was pending
        if (!m_player->IsSeeking() && m_player->CanSeek())
        {
	    // on-demand clip is seek-able
	    m_player->StartSeek();
        }
    }
    else
    {
        // don't do seek right away (see SetEndSeekCalback)
        SetEndSeekCallback(true);
    }
    
}

/*
 * GetNextSeekStep
 * ---------------

⌨️ 快捷键说明

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