chxavplayer.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,374 行 · 第 1/3 页
CPP
1,374 行
/************************************************************************
* chxavplayer.cpp
* ---------------
*
* Synopsis:
* Contains the implementation of the CHXAvPlayer class. This class
* coordinates the client core to play back a file or url.
*
* Target:
* Symbian OS
*
*
* (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
*
*****************************************************************************/
#include "hxtypes.h"
#include "ihxaccesspoint.h"
#include "hxsym_debug.h"
#include "hxsym_leaveutil.h"
#include "hxdebug_hxapi.h"
#include "hxapihelp_player.h"
#include "hxapihelp.h"
#include "hxgroup.h" //IHXGroupSink
#include "chxavcleanstring.h"
#include "chxavramparser.h"
#include "chxavconfignames.h"
#include "chxavcleanupstack.h"
#include "chxavnetconnectui.h"
#include "comptr.h"
#include "comptr_traits.h"
#include "chxavutil.h"
#include "chxavplayer.h"
namespace
{
CHXAvFile::FileType GetFileTypeFromUrlL(const char* pURL)
{
// get path-only part of url in a descriptor
HBufC* pPath = CHXAvUtil::AllocStdPathFromPlayerUrlL(pURL);
AUTO_PUSH_POP_DEL(pPath);
// handle case where local file is a ram/playlist
return CHXAvFile::GetFileType(*pPath);
}
bool HasRemoteURL(IHXValues* pVal)
{
CHXString strURL;
if(val::GetString(pVal, "url", strURL))
{
if(!CHXAvUtil::IsLocal(strURL) || 0 == strURL.Find("helix-sdp"))
{
return true;
}
}
return false;
}
} // locals
// IUnknown implementation body...
BEGIN_INTERFACE_LIST(CHXAvPlayer)
INTERFACE_LIST_ENTRY(IID_IHXClientAdviseSink, IHXClientAdviseSink)
INTERFACE_LIST_ENTRY(IID_IHXAccessPointSelector, IHXAccessPointSelector)
INTERFACE_LIST_ENTRY(IID_IHXErrorSink, IHXErrorSink)
INTERFACE_LIST_ENTRY(IID_IHXGroupSink, IHXGroupSink)
INTERFACE_LIST_ENTRY_DELEGATE_BLIND
(
QueryInterfaceDelegates
)
END_INTERFACE_LIST
HX_RESULT CHXAvPlayer::QueryInterfaceDelegates(REFIID riid, void** ppvObj)
{
if( IsEqualIID(riid, IID_IHXPreferences) )
{
return m_spEngine->GetPrefs()->QueryInterface(riid, ppvObj);
}
else if( IsEqualIID(riid, IID_IHXSiteSupplier) )
{
return m_siteSupplier->QueryInterface(riid, ppvObj);
}
return HXR_NOINTERFACE;
}
/*
* CHXAvPlayer
* -----------
*
*/
CHXAvPlayer::CHXAvPlayer()
: m_clipDuration(0)
, m_clipPos(0)
, m_volumeStep(kVolumeMax / 10) // must match nokia vol control XXXLCM hardcoded
, m_bEnableAutoPlayNext(true)
, m_bIsTruePlaylistLoaded(false)
, m_bResumeOnEndSeek(false)
, m_hxPlayer(0)
, m_startupStage(ssStopped)
, m_bIsRemotePlayback(false)
, m_bAccessPointSetupFailed(false)
{
}
/*
* ~CHXAvPlayer
* -------------
* Destructor.
*
*/
CHXAvPlayer::~CHXAvPlayer()
{
}
/*
* ConstructL
* ----------
*
* Client must call InitPlayerL() before attempting playback
*
*/
void
CHXAvPlayer::ConstructL(const CHXClientEngineManagerPtr& spEngine,
const CHXAvNetConnectUIPtr& pAccessPointSelector)
{
DPRINTF(SYMP_INFO, ("CHXAvPlayer::ConstructL()\n"));
HX_ASSERT(spEngine);
m_spEngine = spEngine;
m_playerState.ConstructL();
// timer for playing current clip
const CHXAvCommand& cmdPlay =
MakeCommand(this, &CHXAvPlayer::PlayCurrent);
m_cbPlay.ConstructL(cmdPlay);
// for convenience
m_prefs = m_spEngine->GetPrefs();
m_factory = m_spEngine->GetFactory();
// ap selector handles some ui logic for selecting and setting access points
m_apSelector = pAccessPointSelector;
}
void CHXAvPlayer::Play(const TDesC& url)
{
HX_ASSERT(CHXAvUtil::IsValidUrl(url));
CHXString str = CHXAvStringUtils::DescToString(url);
Play(str);
}
////////////////////////////////////////
// helper
//
// create a playlist and iterator for ram/playlist
//
void CHXAvPlayer::DoPlaylistInit(const char* pURL)
{
CHXAvURLRep urlRep(pURL);
// these should be reset with each (main url) play attempt
HX_ASSERT(!m_pPlaylist);
HX_ASSERT(!m_pPlaylist);
HX_ASSERT(!m_bIsTruePlaylistLoaded);
m_pPlaylist = CHXAvRAMParser::Parse(urlRep.Path());
if( m_pPlaylist )
{
#ifdef PLAYLIST_END_IN_LST_ONLY
static const char * const k_pPlaylistExt = ".lst"; // XXXLCM
// if ram file has playlist extension, treat it as 'true playlist' (one that can be shuffled, etc.)
INT32 idxDot = urlRep.Path().ReverseFind('.');
if( idxDot != -1 )
{
CHXString ext = urlRep.Path().Mid(idxDot);
m_bIsTruePlaylistLoaded = (0 == ext.CompareNoCase(k_pPlaylistExt));
}
#else
m_bIsTruePlaylistLoaded = true;
#endif
// apply shuffle mode if this is a true playlist
bool bShuffleModeOn = prefs::GetBool(m_prefs, CHXAV_ShuffleMode);
if(m_bIsTruePlaylistLoaded && bShuffleModeOn)
{
m_pPlaylist->Shuffle();
}
m_pPlayItr = new (ELeave) CHXAvPlaylistItr(*m_pPlaylist);
// set iterator loop mode off (even if player 'loop mode' on; that's handled elsewhere)
m_pPlayItr->Loop(false);
// ensure we are at beginning
m_pPlayItr->ResetBegin();
}
}
/*
* Play
* ----
* Handle user command to play the given url.
*
*/
void
CHXAvPlayer::Play(const char *url) // XXXLCM can leave
{
DPRINTF(SYMP_INFO, ("CHXAvPlayer::Play(): url = '%s'\n", url));
HX_ASSERT(m_hxPlayer);
// main url is requested url (ram or single clip)
m_mainUrl = url;
m_playUrl = "";
// reset playlist-related stuff on new main url play attempt
m_pPlaylist = 0;
m_pPlayItr = 0;
m_bIsTruePlaylistLoaded = false;
// see if we can squeeze blood from a turnip
User::CompressAllHeaps();
if(CHXAvUtil::IsFileUrl(url))
{
// handle case where local file is a ram/playlist
CHXAvFile::FileType type = GetFileTypeFromUrlL(url); //XXXLCM can leave
if( CHXAvFile::ftRam == type )
{
DoPlaylistInit(url);
if(m_pPlayItr)
{
DoPlayImp(m_pPlayItr->Current().String());
}
else
{
// invalid ram file
HX_ASSERT(false);
m_playerState.OnError(HXR_INVALID_FILE);
}
}
else
{
// local non-ram file
DoPlayImp(url);
}
}
else
{
// remote url
DoPlayImp(url);
}
}
/*
* PlayCurrent
* ----
* Play the current url
*
*/
void
CHXAvPlayer::PlayCurrent()
{
HX_ASSERT(!m_playUrl.IsEmpty());
DoPlayImp(m_playUrl);
}
/*
* Reset state variables for current clip that won't make sense
* once the clip is unloaded. After a stop the last played
* clip remains "loaded", i.e., ready for re-play. The UI should
* continue to reflect attributes (and provide access to clip info)
* that pertain to the stopped (still-loaded) clip.
*
* A clips is "unloaded" after an advance to next clip in playlist
* or when replaced by a new clip upon a new play request. Also, no
* clip is loaded when this player object is first created.
*
*/
void
CHXAvPlayer::ResetUnloadedClipState()
{
// since play url had changed, current headers and bitrate values no longer apply
m_clipInfo.Reset();
// unknown for next clip
m_clipDuration = 0;
m_bIsRemotePlayback = false;
}
/*
* DoPlayImp
* ------
*
*/
void
CHXAvPlayer::DoPlayImp(const char* url)
{
if( m_playUrl != url)
{
m_playUrl = url;
// reset stuff we won't know until we load
ResetUnloadedClipState();
}
// reset stuff for each play
m_bEnableAutoPlayNext = true;
m_clipPos = 0;
m_startupStage = ssPastInitiate;
m_bAccessPointSetupFailed = false;
m_playerState.OnPlayInitiate(url);
// fixup url in case we need to add duration option to it
CHXString fixedUrl(url); // XXXLCM cleanup stack; function can leave
UINT32 secIntro = prefs::GetUINT32(m_prefs, CHXAV_ClipIntroSecs);
if( m_bIsTruePlaylistLoaded && secIntro != 0 )
{
// Force end of each clip at N seconds into clip. If actual clip
// duration is shorter than N seconds, then the clip will end at
// its proper end time.
static const char * const k_Format = "?end=%lu";
CHXString strOption;
strOption.Format(k_Format, secIntro);
fixedUrl += strOption;
}
HX_ASSERT(m_hxPlayer);
HX_RESULT hxr = m_hxPlayer->OpenURL(fixedUrl);
if( HXR_OK == hxr)
{
hxr = m_hxPlayer->Begin();
if (HXR_OK == hxr)
{
// the file header can be gotten at this point
m_clipInfo.CacheHeadersL(m_hxPlayer);
// we detect need for net connect later on for smil and sdp
if(!m_bAccessPointSetupFailed && !CHXAvUtil::IsLocal(url))
{
OnNetConnect();
}
}
}
if( hxr != HXR_OK )
{
m_playerState.OnError(hxr);
}
}
// heleper
void CHXAvPlayer::OnNetConnect()
{
m_bIsRemotePlayback = true;
if(m_startupStage < ssPastFirstBuffer)
{
m_playerState.OnNetConnect();
}
}
/*
* CanSeek
* ---------
* Returns true if it is safe to seek.
*
*/
bool
CHXAvPlayer::CanSeek() const
{
bool bCanSeek = false;
switch (m_playerState.GetState())
{
case CHXAvPlayerState::Playing:
case CHXAvPlayerState::Seeking:
case CHXAvPlayerState::Paused:
bCanSeek = !m_clipInfo.IsLive(); // && (m_startupStage > ssPastFirstBuffer);
break;
default:
break;
}
return bCanSeek;
}
/*
* CanPause
* ----------
* Return true if we are in a state where it is safe to pause.
*
*/
bool CHXAvPlayer::CanPause() const
{
bool bCanPause = false;
switch (m_playerState.GetState())
{
case CHXAvPlayerState::Playing:
case CHXAvPlayerState::Connecting:
bCanPause = true;
break;
default:
break;
}
return bCanPause;
}
/*
* CanResume
* -----------
* Return true if we can resume from current state.
*/
bool
CHXAvPlayer::CanResume() const
{
return (!m_mainUrl.IsEmpty() && (IsPaused() || IsStopped()));
}
/*
* Stop
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?