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 + -
显示快捷键?