chxavplayer.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:32k
- /************************************************************************
- * 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
- * ----
- * Stop the playback. From user command.
- *
- */
- void
- CHXAvPlayer::Stop()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::Stop()n"));
-
- // prevent automatic playlist/loop advance after user request to stop
- m_bEnableAutoPlayNext = false;
-
- DoStopImp();
- }
- /*
- * DoStopImp
- * ------
- * Stop
- *
- */
- void
- CHXAvPlayer::DoStopImp()
- {
- m_clipPos = 0;
- m_startupStage = ssStopped;
- m_playerState.OnStop();
- HX_ASSERT(m_hxPlayer);
- m_hxPlayer->Stop();
- }
-
- /*
- * Pause
- * -----
- *
- */
- void
- CHXAvPlayer::Pause()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::Pause()n"));
- if ((m_hxPlayer != NULL) && (!m_hxPlayer->IsDone()))
- {
- m_hxPlayer->Pause();
- m_playerState.OnPause();
- }
- }
-
- /*
- * Resume
- * ------
- *
- */
- void
- CHXAvPlayer::Resume()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::Resume()n"));
- if ((m_hxPlayer != NULL) && (!m_hxPlayer->IsDone()))
- {
- m_hxPlayer->Begin();
- }
- }
- /*
- * SetVolume
- * ---------
- *
- */
- void
- CHXAvPlayer::SetVolume(TUint level)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::SetVolume(): level = %dn", level));
- HX_ASSERT(level <= 100);
- HX_ASSERT(m_audioPlayer);
- if( level <= 100 )
- {
- if(m_audioPlayer)
- {
- IHXVolume* pVolume = m_audioPlayer->GetDeviceVolume();
- if( pVolume )
- {
- pVolume->SetVolume(level);
- HX_RELEASE(pVolume);
- }
- }
- m_playerState.OnVolume(level);
- }
- }
-
- void
- CHXAvPlayer::StepVolume(TInt factor)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::StepVolume(): fact = %dn", factor));
- // adjust volume by factor
- TInt level = GetVolume();
- level += m_volumeStep * factor;
- // constrain to valid level
- level = min(kVolumeMax, max(0, level));
- SetVolume(level);
-
- }
- /*
- * GetVolume
- * ---------
- *
- */
- TUint
- CHXAvPlayer::GetVolume() const
- {
- TUint level = 0;
- HX_ASSERT(m_audioPlayer);
- if (m_audioPlayer)
- {
- IHXVolume* pVolume = m_audioPlayer->GetDeviceVolume();
- if( pVolume )
- {
- level = pVolume->GetVolume();
- HX_RELEASE(pVolume);
- }
- }
- return level;
- }
-
- /*
- * Mute
- * ----
- *
- */
- void
- CHXAvPlayer::Mute(bool bToMute)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::Mute('%s')n", dbg::Bool(bToMute)));
- HX_ASSERT(m_audioPlayer);
- if (m_audioPlayer)
- {
- IHXVolume* pVolume = m_audioPlayer->GetDeviceVolume();
- if( pVolume )
- {
- pVolume->SetMute( bToMute );
- HX_RELEASE(pVolume);
- }
- }
- m_playerState.OnMute(bToMute);
- }
- /*
- * IsMuted
- * -------
- *
- */
- bool
- CHXAvPlayer::IsMuted() const
- {
- bool bMute = false;
- HX_ASSERT(m_audioPlayer);
- if (m_audioPlayer)
- {
- IHXVolume* pVolume = m_audioPlayer->GetDeviceVolume();
- if( pVolume )
- {
- bMute = pVolume->GetMute();
- HX_RELEASE(pVolume);
- }
- }
- return bMute;
- }
- /*
- * InitPlayerL
- * -----------
- *
- * Create a new player object and set it up for playback. Call
- * only when player is currently shutdown.
- *
- */
- void CHXAvPlayer::InitPlayerL(CCoeControl* pRenderWindow)
- {
- // player
- HX_ASSERT(!m_hxPlayer);
- m_spEngine->GetEngine()->CreatePlayer(m_hxPlayer.AsRef());
-
- // site supplier (must be done before we setup client context)
- m_siteSupplier = new (ELeave) CHXAvSiteSupplier();
- m_siteSupplier->ConstructL(m_hxPlayer, pRenderWindow);
- m_hxPlayer->SetClientContext(static_cast<IHXClientAdviseSink*>(this)); // arbitrary unknown
-
- // set us up to observe player events
- m_hxPlayer->AddAdviseSink(this);
-
- // set us up to observer error messages
- comptr<IHXErrorSinkControl> control;
- control.From(m_hxPlayer);
- control->AddErrorSink(this, HXLOG_EMERG, HXLOG_INFO);
- // set us up as ap selector
- m_apManager.From(m_hxPlayer);
- if(m_apManager)
- {
- m_apManager->RegisterSelector(this);
- }
-
- // grab some interfaces
- m_audioPlayer.From(m_hxPlayer);
- // set up to receive group/track events
- comptr<IHXGroupManager> groupMgr;
- groupMgr.From(m_hxPlayer);
- if(groupMgr)
- {
- groupMgr->AddSink(this);
- }
- }
- // IHXAccessPointSelector
- STDMETHODIMP
- CHXAvPlayer::SelectAccessPoint(IHXAccessPointSelectorResponse* pResponse)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::SelectAccessPoint()n"));
- HX_RESULT hr = HXR_OK;
- if(m_apSelector)
- {
- HX_ASSERT(m_apManager);
- TRAPD(err, hr = m_apSelector->DoSelectAccessPointL(m_apManager, pResponse));
- if(err != KErrNone)
- {
- hr = HXR_FAIL;
- }
- }
- if(SUCCEEDED(hr))
- {
- // just in case; we should detect this via other methods
- OnNetConnect();
- }
- else
- {
- // some pending client core tasks (e.g., group sink notifications) get processed
- // before this error is detected and reported; we want to ignore these, hence this
- // pulchritudinous flag
- m_bAccessPointSetupFailed = true;
- }
- return hr;
- }
- /*
- * ShutDown
- * --------
- *
- * Release and destroy the player object. The player does not unload
- * renderers and sites until it closes or a new presentation is opened.
- *
- * UI owner must call this to free references held by client core (so that
- * subsequent release of this object results in deletion)
- *
- * Undoes everything done in InitPlayerL
- *
- * Note: clip, playlist and header info remains valid
- */
- void
- CHXAvPlayer::ShutDown()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::ShutDown()n"));
- //HX_ASSERT(m_hxPlayer);
- if( m_hxPlayer )
- {
- // stop and remove sinks (just in case; probably not really necessary)
- if(!m_hxPlayer->IsDone())
- {
- m_hxPlayer->Stop();
- }
- m_hxPlayer->RemoveAdviseSink(this);
- comptr<IHXErrorSinkControl> control;
- control.From(m_hxPlayer);
- control->RemoveErrorSink(this);
- control.Reset();
- comptr<IHXGroupManager> groupMgr;
- groupMgr.From(m_hxPlayer);
- if(groupMgr)
- {
- groupMgr->RemoveSink(this);
- }
- // unregister with access point manager
- if(m_apManager)
- {
- m_apManager->UnregisterSelector(this);
- }
- m_spEngine->GetEngine()->ClosePlayer(m_hxPlayer);
- m_audioPlayer = 0;
- m_siteSupplier = 0;
- m_hxPlayer = 0;
- m_apManager = 0;
- }
- // reset stuff associated with previously active HX player
- m_mainUrl = "";
- m_playUrl = "";
- m_pPlaylist = 0;
- m_pPlayItr = 0;
- m_bIsTruePlaylistLoaded = false;
- ResetUnloadedClipState();
- }
- /*
- * GetClipTime
- * -----------
- * Returns the point in the timeline where we are currently.
- *
- */
- ULONG32
- CHXAvPlayer::GetClipTime() const
- {
- // note: we don't use IHXPlayer::GetCurrentPlayTime() so we have better control over this value
- return m_clipPos;
- }
- /*
- * EndSeek
- * -------
- * Called when user stops seeking
- *
- */
- void
- CHXAvPlayer::EndSeek()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::EndSeek()n"));
- HX_ASSERT(m_hxPlayer);
- if( m_clipPos >= GetClipDuration() )
- {
- // seek to end
- DoStopImp();
- }
- else
- {
- HX_RESULT hr = m_hxPlayer->Seek(m_clipPos);
- if( SUCCEEDED(hr) )
- {
- // auto-resume playback if we were playing when we began seeking
- if (m_bResumeOnEndSeek)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::EndSeek(): resuming...n"));
- hr = m_hxPlayer->Begin();
- }
- else
- {
- m_playerState.OnPause();
- }
- }
- if(FAILED(hr))
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::EndSeek(): failed to resume player after seek ('%s')n", dbg::ErrorCode(hr)));
- DoStopImp();
- }
- }
- m_bResumeOnEndSeek = false;
- }
- /*
- * StartSeek
- * ---------
- * Called when user begins seeking (drags slider, presses seek button, etc.)
- *
- */
- void
- CHXAvPlayer::StartSeek()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::StartSeek()n"));
- bool bIsPaused = (m_playerState.GetState() == CHXAvPlayerState::Paused);
- m_bResumeOnEndSeek = !bIsPaused;
- m_playerState.OnBeginSeek();
- // we must pause while user is seeking
- if( !bIsPaused )
- {
- m_hxPlayer->Pause();
- }
- }
- /*
- * SetSeekPoint
- * ------------
- * update current seek point as user moves slider/position around
- *
- */
- void
- CHXAvPlayer::SetSeekPoint(ULONG32 time)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::SetSeekPoint(): time = %lun", time));
- HX_ASSERT(IsSeeking());
-
- ULONG32 duration = GetClipDuration();
- if( time > duration )
- {
- //
- // set time to duration so when we attempt to resume
- // we will automatically go on to the next clip
- //
- time = duration;
- }
- m_clipPos = time;
- m_playerState.OnNewPos(time);
-
- }
- //IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnPosLength(UINT32 ulPosition, UINT32 ulLength)
- {
- //DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPosLength(): pos = %lun", ulPosition));
- if(ulPosition > 0)
- {
- // we assume we get a buffer message before OnPosLength() in every case
- HX_ASSERT(m_startupStage >= ssPastFirstBuffer);
- m_startupStage = ssPastTimerStarted;
- }
- m_clipPos = ulPosition;
- m_clipDuration = ulLength;
- if(ulLength >0)
- {
- m_playerState.OnNewPos(ulPosition);
- }
- return HXR_OK;
- }
- ////////////////////////////////
- //
- TInt CHXAvPlayer::GetPlaylistCurrentIndex() const
- {
- HX_ASSERT(m_pPlayItr);
- return m_pPlayItr->Offset();
- }
- TInt CHXAvPlayer::GetPlaylistItemCount() const
- {
- HX_ASSERT(m_pPlaylist);
- return m_pPlaylist->Length();
- }
- ////////////////////////////////////////////
- // user command to move to next or previous item in playlist
- //
- // from user request
- //
- void CHXAvPlayer::AdvancePlaylist(TUint flag)
- {
- if(!m_pPlayItr)
- {
- return;
- }
- // move forward or backward in playlist
- HandlePlaylistAdvance(flag);
- if( CHXAvPlayerState::Stopped != m_playerState.GetState() )
- {
- // stop current clip as soon as user moves through playlist
- m_bEnableAutoPlayNext = false;
- DoStopImp();
- }
- }
- ////////////////////////////////////////////
- //
- // return true if playlist end was reached
- //
- bool CHXAvPlayer::HandlePlaylistAdvance(TUint flag)
- {
- HX_ASSERT(m_pPlayItr);
-
- bool bReachedEnd = false;
- // temporarily set playlist iter loop mode on so we loop around
- m_pPlayItr->Loop( (flag & advanceLoop) != 0 );
- if (flag & advanceNext)
- {
- m_pPlayItr->Next();
- }
- else
- {
- HX_ASSERT(flag & advancePrev);
- m_pPlayItr->Prev();
- }
- if(!m_pPlayItr->More())
- {
- m_pPlayItr->ResetBegin();
- bReachedEnd = true;
- }
- m_playUrl = m_pPlayItr->Current().String();
- // restore playlist iter loop mode
- m_pPlayItr->Loop(false);
- // play url has changed - reset associated state variables
- ResetUnloadedClipState();
- m_playerState.OnAdvancePlaylist();
- return bReachedEnd;
-
- }
- /*
- * IHXClientAdviseSink
- * OnPresentationOpened
- * --------------------
- *
- */
- STDMETHODIMP
- CHXAvPlayer::OnPresentationOpened()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPresentationOpened()n"));
- HX_ASSERT(m_hxPlayer != NULL);
- m_startupStage = ssPastOpenPres;
- // now we should be able to obtain all headers for main source (in case of smil
- // sub-sources will not be there yet -- see OnBuffering)
- m_clipInfo.CacheHeadersL(m_hxPlayer);
- // see if we are video-only and/or live
- m_clipInfo.CachePresentationInfoL(m_hxPlayer);
-
- // get request headers...
- comptr<IHXPlayer2> play2;
- play2.From(m_hxPlayer);
- HX_ASSERT(play2);
-
- comptr<IHXRequest> req;
- play2->GetRequest(req.AsRef());
- HX_ASSERT(req);
-
- // possibly save some request info
- m_clipInfo.CacheRequestInfo(req);
- m_playerState.OnLoadSession(req);
-
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnPresentationClosed()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPresentationClosed()n"));
- HX_ASSERT(CHXAvPlayerState::Stopped == m_playerState.GetState()); // we expect OnStop() first
-
- m_playerState.OnStop(); // just in case
- if( m_bEnableAutoPlayNext )
- {
- // current clip ended by playing out; try to advance to next clip or loop
- bool bLoopModeEnabled = prefs::GetBool(m_prefs, CHXAV_LoopMode);
- bool bDoPlay = true;
- if( m_pPlayItr )
- {
- TUint af = advanceNext;
- if( bLoopModeEnabled )
- {
- af |= advanceLoop;
- }
- // advance through playlist
- bool bReachedEnd = HandlePlaylistAdvance(af);
- if( bReachedEnd && !bLoopModeEnabled )
- {
- // stop at end of playlist when loop mode is off
- bDoPlay = false;
- }
- }
- else
- {
- bDoPlay = bLoopModeEnabled;
- }
-
- if( bDoPlay )
- {
- // if we call PlayCurrent() here, we get an immediate OnStop() and OnPresentationClosed()
- m_cbPlay.Set(10);
- }
- }
-
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnStatisticsChanged()
- {
- #if defined(HELIX_FEATURE_DPRINTF)
- char szBuff[100];
- for(UINT16 idx = 0; /*NULL*/; ++idx)
- {
- sprintf(szBuff, "Statistics.Player%u", idx );
- if(!dbg::DumpRegistry(m_spEngine->GetEngine(), szBuff))
- {
- break;
- }
- }
- #endif
- return HXR_OK;
- }
-
-
- // IHXClientAdviseSink
- //
- // called when player object begins seek, just after
- // user finishes setting seek target; during this period
- // we expect to receive buffer notifications until OnPostSeek()
- // is called
- STDMETHODIMP
- CHXAvPlayer::OnPreSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPreSeek()n"));
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnPostSeek(ULONG32 ulOldTime, ULONG32 ulNewTime)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPostSeek()n"));
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnStop()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnStop()n"));
- m_clipPos = 0;
- m_playerState.OnStop();
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnPause(ULONG32 ulTime)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnPause()n"));
- if( m_playerState.GetState() != CHXAvPlayerState::Seeking)
- {
- m_playerState.OnPause();
- }
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- //
- // called a) after renderers are initialized (before open pres) b) after EndSeek
- STDMETHODIMP
- CHXAvPlayer::OnBegin(ULONG32 ulTime)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnBegin()n"));
- if(m_startupStage >= ssPastFirstBuffer)
- {
- m_playerState.OnResume();
- }
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::OnBuffering(ULONG32 type, UINT16 unPercentComplete)
- {
- //DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnBuffering(type = %lu('%s'), percent = %u)n", type, dbg::BufferReason(type), unPercentComplete));
- if(m_startupStage < ssPastFirstBuffer)
- {
- m_startupStage = ssPastFirstBuffer;
- dbg::DumpHeaders(m_hxPlayer);
- //XXXLCM consider just updating header and presentation info, etc. in call to
- // GetClipInfo() (or method such as UpdateClipInfo() that can be called beforehand);
- // we'd still have to cache the info when we stop; this will clip info is up to date
- // if sources are added and removed as presentation goes along (for smil case)
- // for smil all sources should be created by now
- m_clipInfo.CacheHeadersL(m_hxPlayer);
- m_clipInfo.CacheURLsL(m_hxPlayer);
- m_clipInfo.CachePresentationInfoL(m_hxPlayer);
- // now is earliest time to get best stream bitrate values (i.e.,
- // subscribed surestream bitrate will be known, if applicable)
- m_clipInfo.SaveStreamBitrateValuesL(m_hxPlayer);
- }
- //
- // Buffering state is independent of main player state
- //
- // - cannot assume we get a value of 0 for first buffer
- // - can assume we get 100 for buffer complete
- // - we often get repeated calls with no change in value from last time
- // - sometimes after 100 we get more buffering (re-buffering)
- // - we do not get other messages indicating play is resuming
- // - if seeking, we do get subsequent OnPostSeek
- //
-
- m_playerState.OnBuffering(type, unPercentComplete);
- return HXR_OK;
- }
-
- // IHXClientAdviseSink
- //
- // called when about to resolve host name via dns lookup
- STDMETHODIMP
- CHXAvPlayer::OnContacting(const char* pHostName)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnContacting(): '%s'n", pHostName));
- return HXR_OK;
- }
- // IHXClientAdviseSink
- STDMETHODIMP
- CHXAvPlayer::ErrorOccurred(const UINT8 unSeverity,
- const ULONG32 ulHXCode,
- const ULONG32 ulUserCode,
- const char* pUserString,
- const char* pMoreInfoURL)
- {
- // do not continue through playlist or loop after an error
- m_bEnableAutoPlayNext = false;
-
- if( m_clipInfo.GetSourceCount() > 0 && m_clipInfo.GetStreamCount(0) == 0 )
- {
- //
- // No stream headers are currently cached for the first source.
- // It is possible that they are now available. (This can be the
- // case if the error occurs after the request is issued but before
- // the presentation opens.) We now try to cache the stream
- // headers in order to enable the user to be able to see
- // as much clip info as possible after this error.
- //
- HX_ASSERT(m_hxPlayer);
- UINT32 streamCount = player::GetStreamCount(m_hxPlayer, 0);
- if(streamCount > 0)
- {
- m_clipInfo.CacheHeadersL(m_hxPlayer);
- }
- }
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::OnError(): code = 0x%08x(%s), user code = 0x%08x', sev = %u(%s)n", ulHXCode, dbg::ErrorCode(ulHXCode), ulUserCode, unSeverity, dbg::SevCode(unSeverity)));
- if(!m_bAccessPointSetupFailed)
- {
- m_playerState.OnError(ulHXCode);
- }
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::GroupAdded(UINT16 uGroupIndex,IHXGroup* pGroup)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::GroupAdded()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::GroupRemoved(UINT16 uGroupIndex, IHXGroup* pGroup)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::GroupRemoved()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::AllGroupsRemoved()
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::AllGroupsRemoved()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::TrackAdded(UINT16 uGroupIndex, UINT16 uTrackIndex,IHXValues* pTrack)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::TrackAdded(): group idx = %u; track idx = %un", uGroupIndex, uTrackIndex));
- dbg::DumpObject(pTrack);
- if(!m_bAccessPointSetupFailed)
- {
- // for smil case
- if(HasRemoteURL(pTrack))
- {
- //XXXLCM to be 100% correct we should look at other track notifications
- //and deal convoluted cases where we have both network and local links. For
- //example, if we have a network source followed by a local source in a smil
- //file we will incorrectly advertise that the current source is remote once
- //the local source becomes current
-
- OnNetConnect();
- }
- }
-
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::TrackRemoved(UINT16 uGroupIndex, UINT16 uTrackIndex, IHXValues* pTrack)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::TrackRemoved()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::TrackStarted(UINT16 uGroupIndex, UINT16 uTrackIndex, IHXValues* pTrack)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::TrackStarted()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::TrackStopped(UINT16 uGroupIndex, UINT16 uTrackIndex, IHXValues* pTrack)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::TrackStopped()n"));
- return HXR_OK;
- }
- //IHXGroupSink
- STDMETHODIMP
- CHXAvPlayer::CurrentGroupSet(UINT16 uGroupIndex, IHXGroup* pGroup)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::CurrentGroupSet()n"));
- if(!m_bAccessPointSetupFailed)
- {
- // look for a non-local url in this group
- UINT16 count = pGroup->GetTrackCount();
- for(UINT16 idx = 0; idx < count; ++idx)
- {
- DPRINTF(SYMP_INFO, ("CHXAvPlayer::CurrentGroupSet(): group %un", idx));
- comptr<IHXValues> val;
- pGroup->GetTrack(idx, val.AsRef());
- dbg::DumpObject(val); // 'url'
-
- if(HasRemoteURL(val))
- {
- OnNetConnect();
- }
- }
- }
- return HXR_OK;
- }