diff -r 839377eedc2b -r befca0ec475f videocollection/hgmyvideos/src/vcxhgmyvideosvideodataupdater.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videocollection/hgmyvideos/src/vcxhgmyvideosvideodataupdater.cpp Wed Sep 01 12:30:28 2010 +0100 @@ -0,0 +1,1048 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: CVcxHgMyVideosVideoDataUpdater implementation* +*/ + + + + +// INCLUDE FILES +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include // DRM +#include + +#include "IptvDebug.h" +#include +#include +#include "vcxhgmyvideosmodel.h" +#include "vcxhgmyvideosmainview.h" +#include "vcxhgmyvideosvideolist.h" +#include "vcxhgmyvideosvideodataupdater.h" +#include "vcxhgmyvideosindicatorhelper.h" +#include "vcxhgmyvideosthumbnailmanager.h" + +const TInt KRefreshTimerInterval( 1000000 ); // 1 second +const TInt KMaxThumbnailReqs( 2 ); // Max count of peek and get reqs combined +const TInt KMaxThumbnailGetReqs( 1 ); // Max count of get reqs +const TInt KMaxPredictiveSelect( 10 ); // Max range for selecting items before/after visible area +const TInt KScrollCheckInterval( 250000 ); // 0.25 seconds + +// ----------------------------------------------------------------------------- +// TimeStamp +// ----------------------------------------------------------------------------- +// +static TInt64 TimeStamp() + { + TTime time; + time.UniversalTime(); + return time.Int64(); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::NewL() +// ----------------------------------------------------------------------------- +// +CVcxHgMyVideosVideoDataUpdater* CVcxHgMyVideosVideoDataUpdater::NewL( + CVcxHgMyVideosModel& aModel, + CHgScroller& aScroller, + CVcxHgMyVideosVideoList& aVideoArray, + CMyVideosIndicator& aVideosIndicator ) + { + CVcxHgMyVideosVideoDataUpdater* self = + CVcxHgMyVideosVideoDataUpdater::NewLC( aModel, + aScroller, + aVideoArray, + aVideosIndicator ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::NewLC() +// ----------------------------------------------------------------------------- +// +CVcxHgMyVideosVideoDataUpdater* CVcxHgMyVideosVideoDataUpdater::NewLC( + CVcxHgMyVideosModel& aModel, + CHgScroller& aScroller, + CVcxHgMyVideosVideoList& aVideoArray, + CMyVideosIndicator& aVideosIndicator) + { + CVcxHgMyVideosVideoDataUpdater* self = + new (ELeave) CVcxHgMyVideosVideoDataUpdater( aModel, + aScroller, + aVideoArray, + aVideosIndicator ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::CVcxHgMyVideosVideoDataUpdater() +// ----------------------------------------------------------------------------- +// +CVcxHgMyVideosVideoDataUpdater::CVcxHgMyVideosVideoDataUpdater( + CVcxHgMyVideosModel& aModel, + CHgScroller& aScroller, + CVcxHgMyVideosVideoList& aVideoArray, + CMyVideosIndicator& aVideosIndicator ) + : CActive( EPriorityStandard ), + iModel( aModel ), + iScroller( aScroller ), + iVideoArray( aVideoArray ), + iVideosIndicator( aVideosIndicator ), + iPaused( EFalse ) + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ConstructL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::ConstructL() + { + iRefreshTimer = CPeriodic::NewL( CActive::EPriorityStandard ); + iRetryTimer = CPeriodic::NewL( CActive::EPriorityStandard ); + iModel.ThumbnailManager().AddObserverL( *this ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::InfoArrayChanged() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::InfoArrayChanged() + { + // Can we optimise this? Many times new video list contains lot of items + // from the old one. But how to make sure there isn't any radical changes... + + CancelAndDeleteFetchArray(); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::~CVcxHgMyVideosVideoDataUpdater() +// ----------------------------------------------------------------------------- +// +CVcxHgMyVideosVideoDataUpdater::~CVcxHgMyVideosVideoDataUpdater() + { + iModel.ThumbnailManager().RemoveObserver( *this ); + Cancel(); + delete iRefreshTimer; // Cancels active timer + delete iRetryTimer; + iFetchArray.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::SetPausedL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::SetPausedL( TBool aPaused ) + { + iPaused = aPaused; + + if ( ! iPaused ) + { + ContinueVideoDataFetchingL(); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RequestDataL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::RequestDataL( TMPXItemId aMPXItemId ) + { + AddItemToFetchArrayL( aMPXItemId ); + ContinueVideoDataFetchingL(); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::AddToRequestBufferL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::AddToRequestBufferL( TMPXItemId aMPXItemId ) + { + AddItemToFetchArrayL( aMPXItemId ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::FlushRequestBufferL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::FlushRequestBufferL() + { + ContinueVideoDataFetchingL(); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ReleaseData() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::ReleaseData( TMPXItemId aMPXItemId ) + { + TInt index = IndexByMPXItemId( aMPXItemId ); + if ( index >= 0 ) + { + RemoveItem( index ); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::PrepareForMoveOrDelete() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::PrepareForMoveOrDelete( TMPXItemId aMPXItemId ) + { + TInt index = IndexByMPXItemId( aMPXItemId ); + if ( index >= 0 ) + { + RemoveAndCancelThumbnailGeneration( index ); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RemoveAndCancelThumbnailGeneration() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::RemoveAndCancelThumbnailGeneration( TInt aIndex ) + { + if ( aIndex >= 0 && aIndex < iFetchArray.Count() ) + { + // Can be enabled when cancellation of (hd) thumbnail gets faster and + // does not hang up UI + CancelActivities( aIndex ); + delete iFetchArray[aIndex]; + iFetchArray.Remove( aIndex ); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RemoveItem() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::RemoveItem( TInt aIndex ) + { + if ( aIndex >= 0 && aIndex < iFetchArray.Count() ) + { + CVcxHgMyVideosVideoData* item = iFetchArray[aIndex]; + + // When scrolling around canceling thumbnail creation is sometimes so slow + // that it hangs UI for while. Thumbnail is needed sooner or later anyway. + // Therefore let creation get finished in peace. It is possible to fetch already + // created thumbs during creation but not during hang up. + if ( item && !CancelNeeded( *item ) ) + { + delete item; + iFetchArray.Remove( aIndex ); + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::AddItemToFetchArrayL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::AddItemToFetchArrayL( TMPXItemId aMPXItemId ) + { + CVcxHgMyVideosVideoData* newItem = CVcxHgMyVideosVideoData::NewLC(); + newItem->SetMPXItemId( aMPXItemId ); + iFetchArray.AppendL( newItem ); + + CleanupStack::Pop( newItem ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::CancelActivities() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::CancelActivities( TInt aIndex ) + { + if ( aIndex >= 0 && aIndex < iFetchArray.Count() ) + { + CVcxHgMyVideosVideoData* item = iFetchArray[aIndex]; + if ( item && CancelNeeded( *item ) ) + { + iModel.ThumbnailManager().Cancel( item->ThumbnailConversionId() ); + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::CancelAndDeleteFetchArray() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::CancelAndDeleteFetchArray() + { + TInt count = iFetchArray.Count(); + for ( TInt i = 0; i < count; i++ ) + { + CancelActivities( i ); + } + iFetchArray.ResetAndDestroy(); + + iPreviousFirstScrollerIndexTime = 0; + iPreviousFirstScrollerIndex = iScroller.FirstIndexOnScreen(); + iPreviousModifiedIndexOnScreen = EFalse; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ContinueVideoDataFetchingL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::ContinueVideoDataFetchingL() + { + iRetryTimer->Cancel(); + if ( !iPaused && iVideoArray.VideoCount() > 0 && iFetchArray.Count() > 0 ) + { + TInt64 time = TimeStamp(); + TBool refreshTimerNeeded = EFalse; + TInt peekReqs = 0; + TInt getReqs = 0; + GetActiveRequestCount( peekReqs, getReqs ); + TInt reqs = peekReqs + getReqs; + if ( reqs < KMaxThumbnailReqs ) + { + CVcxHgMyVideosVideoData::TVideoDataState state = + CVcxHgMyVideosVideoData::EVideoDataStateNone; + CVcxHgMyVideosVideoData* prevItem = NULL; + CVcxHgMyVideosVideoData* item = NULL; + do + { + TInt err = KErrNone; + prevItem = item; + if ( !SelectNextIndexL( getReqs >= KMaxThumbnailGetReqs ) ) + { + // Nothing to be started + if ( !reqs && iFetchArray.Count() > 0 ) + { + // To ensure that thumbnail creation continues after + // disabled while scrolling + iRetryTimer->Start( KScrollCheckInterval, KScrollCheckInterval, + TCallBack( RetryTimerCallBack, this ) ); + iPreviousFirstScrollerIndexTime = 0; // Force scroll check update + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # ContinueVideoDataFetchingL # iRetryTimer start" ); + } + break; + } + item = iFetchArray[0]; + state = item->State(); + if ( state == CVcxHgMyVideosVideoData::EVideoDataStateNone ) + { + // Try first a quick peek with thumbnail creation denied + TRAP( err, StartThumbnailL( *item, ETrue ) ); + if( err == KErrNone ) + { + ++reqs; + refreshTimerNeeded = ETrue; + } + } + else if ( state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekFinished ) + { + if ( getReqs < KMaxThumbnailGetReqs ) + { + // Try then get with thumbnail creation allowed + TRAP( err, StartThumbnailL( *item, EFalse ) ); + if ( err == KErrNone ) + { + ++reqs; + ++getReqs; + refreshTimerNeeded = ETrue; + } + } + } + if ( err != KErrNone ) + { + RemoveItem( 0 ); + } + } + while ( iFetchArray.Count() > 0 && reqs < KMaxThumbnailReqs && prevItem != item ); + } + if ( refreshTimerNeeded && !iRefreshTimer->IsActive() ) + { + iRefreshTimer->Start( KRefreshTimerInterval, KRefreshTimerInterval, + TCallBack( RefreshTimerCallBack, this ) ); + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # ContinueVideoDataFetchingL # iRefreshTimer start" ); + } + if ( time - iPreviousFirstScrollerIndexTime >= KScrollCheckInterval ) + { + // Store values for scroll direction check + iPreviousFirstScrollerIndexTime = time; + iPreviousFirstScrollerIndex = iScroller.FirstIndexOnScreen(); + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL( CVcxHgMyVideosVideoData& aVideoData ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL() ENTER" ); + + TInt index = iVideoArray.IndexByMPXItemId( aVideoData.MPXItemId() ); + + if ( index >= 0 && index < iScroller.ItemCount() ) + { + TBool drmUpdate = aVideoData.DrmProtected(); + CHgItem& listItem = iScroller.ItemL( index ); + + if ( aVideoData.Thumbnail() ) + { + CGulIcon* thumbnail = CGulIcon::NewL( aVideoData.Thumbnail( ETrue ) ); + listItem.SetIcon( thumbnail ); + CMPXMedia* media = iVideoArray.MPXMediaByMPXItemId( aVideoData.MPXItemId() ); + if ( iVideosIndicator.IsIndicatorShown( *media ) ) + { + IPTVLOGSTRING_LOW_LEVEL("CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL() has icon, has indicator" ); + listItem.SetFlags( CHgItem::EHgItemFlagsIconOverlayIndicator ); + } + else + { + IPTVLOGSTRING_LOW_LEVEL("CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL() has icon, no indicator" ); + listItem.ClearFlags( CHgItem::EHgItemFlagsIconOverlayIndicator ); + } + } + + if ( drmUpdate ) + { + TVcxHgMyVideosIndicatorHelper::TIndicatorDrmStatus drmStatus; + CMPXMedia* media = iVideoArray.MPXMedia( index ); + + if ( media ) + { + TVcxHgMyVideosIndicatorHelper indicatorHelper; + TInt indicator1( 0 ); + TInt indicator2( 0 ); + + if ( aVideoData.ValidDrmRights() ) + { + drmStatus = TVcxHgMyVideosIndicatorHelper::EIndicatorDrmStatusValid; + } + else + { + drmStatus = TVcxHgMyVideosIndicatorHelper::EIndicatorDrmStatusExpired; + } + + TBool isNewVideo( EFalse ); + if ( media->IsSupported( KMPXMediaGeneralFlags ) ) + { + if ( media->ValueTObjectL( KMPXMediaGeneralFlags ) & + EVcxMyVideosVideoNew ) + { + isNewVideo = ETrue; + } + } + + indicatorHelper.GetIndicatorsForVideoL( + iModel, + isNewVideo, + EFalse, // *Recordings* + media->ValueText( KMPXMediaGeneralUri ), + drmStatus, + indicator1, + indicator2 ); + + if ( indicator1 ) + { + listItem.SetFlags( indicator1 ); + } + if ( indicator2 ) + { + listItem.SetFlags( indicator2 ); + } + } + } + + if ( ListRefreshNeeded( index ) ) + { + RefreshScreen(); + } + } + IPTVLOGSTRING_LOW_LEVEL("CVcxHgMyVideosVideoDataUpdater::UpdateVideoDataToUiL() RETURN" ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::IndexByMPXItemId() +// ----------------------------------------------------------------------------- +// +TInt CVcxHgMyVideosVideoDataUpdater::IndexByMPXItemId( TMPXItemId aMPXItemId ) + { + TInt count = iFetchArray.Count(); + for ( TInt i = 0; i < count; i++ ) + { + if ( iFetchArray[i]->MPXItemId() == aMPXItemId ) + { + return i; + } + } + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::SelectNextIndexL() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::SelectNextIndexL( TBool aSelectForPeekOnly ) + { + TBool selected = EFalse; + if ( iScroller.ItemCount() > 0 ) + { + TInt firstIndexOnScreen = 0; + TInt lastIndexOnScreen = 0; + TInt lastIndex = 0; + GetScrollerArea( firstIndexOnScreen, lastIndexOnScreen, lastIndex ); + + // Determine scroll direction for optimal selection + TInt maxPredict = KMaxPredictiveSelect; + TBool scrollUp = iPreviousFirstScrollerIndex > firstIndexOnScreen; + TBool scrollDown = iPreviousFirstScrollerIndex < firstIndexOnScreen; + if ( scrollUp || scrollDown ) + { + if ( scrollUp ) + { + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater # scroll up" ); + } + else + { + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater # scroll down" ); + } + aSelectForPeekOnly = ETrue; // Disable thumb creation while scrolling + } + else + { + maxPredict /= 2; // Split range when checking both directions + } + + if ( !aSelectForPeekOnly || scrollUp ) + { + // Try visible area first with thumb creation disabled to get + // already created thumbs as fast as possible + selected = TrySelectFromScrollerAreaL( firstIndexOnScreen, + lastIndexOnScreen, + ETrue ); + } + if ( !selected && !scrollUp ) + { + // Try visible area and items below + TInt end = Min( lastIndexOnScreen + maxPredict, lastIndex ); + selected = TrySelectFromScrollerAreaL( firstIndexOnScreen, end, + aSelectForPeekOnly ); + } + if ( !selected && !scrollDown && firstIndexOnScreen > 0 ) + { + // Try items above visible area + TInt end = Max( firstIndexOnScreen - maxPredict - 1, 0 ); + selected = TrySelectFromScrollerAreaL( firstIndexOnScreen - 1, end, + aSelectForPeekOnly ); + } + if ( !selected ) + { + // Try any item + TInt count = iFetchArray.Count(); + for ( TInt i = 0; i < count; i++ ) + { + if ( TrySelectL( i, aSelectForPeekOnly ) ) + { + selected = ETrue; + break; + } + } + } + } + return selected; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RefreshTimerCallBack() +// ----------------------------------------------------------------------------- +// +TInt CVcxHgMyVideosVideoDataUpdater::RefreshTimerCallBack( TAny* aAny ) + { + CVcxHgMyVideosVideoDataUpdater* self = static_cast( aAny ); + if ( !self->iPaused && self->iFetchArray.Count() > 0 ) + { + // Do refresh only if on screen item has been modified + if ( self->iPreviousModifiedIndexOnScreen ) + { + self->iPreviousModifiedIndexOnScreen = EFalse; // Reset refresh checking + self->RefreshScreen(); + } + } + else + { + self->iRefreshTimer->Cancel(); + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # RefreshTimerCallBack # iRefreshTimer stop" ); + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RefreshScreen() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::RefreshScreen() + { + IPTVLOGSTRING_LOW_LEVEL( "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater::RefreshScreen()" ); + iScroller.DrawDeferred(); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ListRefreshNeeded() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::ListRefreshNeeded( TInt aIndex ) + { + TInt firstIndexOnScreen = 0; + TInt lastIndexOnScreen = 0; + TInt lastIndex = 0; + GetScrollerArea( firstIndexOnScreen, lastIndexOnScreen, lastIndex ); + + TBool modifiedIndexOnScreen = aIndex >= firstIndexOnScreen && + aIndex <= lastIndexOnScreen; + TBool refreshNeeded( EFalse ); + + // Refresh rules: + // 1) Refresh if off screen item is detected after on screen item + // 2) Refresh if item is the last + if ( ( iPreviousModifiedIndexOnScreen && !modifiedIndexOnScreen ) || + iFetchArray.Count() <= 1 ) + { + // Restart refresh timer if there are items left after current one + iRefreshTimer->Cancel(); + if ( iFetchArray.Count() > 1 ) + { + iRefreshTimer->Start( KRefreshTimerInterval, KRefreshTimerInterval, + TCallBack( RefreshTimerCallBack, this ) ); + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # ListRefreshNeeded # iRefreshTimer start" ); + } + else + { + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # ListRefreshNeeded # iRefreshTimer stop" ); + } + refreshNeeded = ETrue; + } + iPreviousModifiedIndexOnScreen = modifiedIndexOnScreen; + return refreshNeeded; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ThumbnailPreviewReady() +// From MThumbnailManagerObserver, not used in Video Center. +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::ThumbnailPreviewReady( MThumbnailData& /*aThumbnail*/, + TThumbnailRequestId /*aId*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::ThumbnailReady() +// From MThumbnailManagerObserver +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::ThumbnailReady( TInt aError, + MThumbnailData& aThumbnail, + TThumbnailRequestId aId ) + { + IPTVLOGSTRING3_LOW_LEVEL( + "MPX My Videos UI # ThumbnailReady(error=%d, thumbID=%d)", aError, aId ); + + TInt count = iFetchArray.Count(); + for( TInt i = 0; i < count; ++i ) + { + CVcxHgMyVideosVideoData* item = iFetchArray[i]; + if ( aId == item->ThumbnailConversionId() ) + { + if ( aError == KErrNone || + aError == KErrCompletion || // Accept blacklisted + item->State() == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailStarted ) + { + // Never delete this, ownership gone to Ganes list + item->SetThumbnail( aError == KErrNone ? aThumbnail.DetachBitmap() : NULL ); + item->SetState( CVcxHgMyVideosVideoData::EVideoDataStateThumbnailFinished ); + StartFinalActions(); + } + else if ( aError == KErrNotFound && + item->State() == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekStarted ) + { + // Try getting thumbnail with create allowed when peek failed with not found + item->SetState( CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekFinished ); + } + else + { + // Stop thumbnail peek attemps + item->SetState( CVcxHgMyVideosVideoData::EVideoDataStateThumbnailFinished ); + StartFinalActions(); + } + + TRAPD( err, ContinueVideoDataFetchingL() ); + if ( err != KErrNone ) + { + IPTVLOGSTRING2_LOW_LEVEL( + "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater::ThumbnailReady, err = %d", + err ); + } + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RunL() +// From CActive +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::RunL() + { + if ( !iPaused ) + { + TInt i = iFetchArray.Count() - 1; + while( i >= 0 ) + { + CVcxHgMyVideosVideoData* item = iFetchArray[i]; + if ( item->State() == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailFinished ) + { + TRAP_IGNORE( + { + CheckDrmL( *item ); + UpdateVideoDataToUiL( *item ); + } ); + delete item; + iFetchArray.Remove(i); +#if 0 + if ( iFetchArray.Count() > 0 ) + { + // If drm checking is time consuming, proceed finalisation later + StartFinalActions(); + break; + } +#endif + } + --i; + } + if ( !iFetchArray.Count() ) + { + // No items left, timers are not needed anymore + iRefreshTimer->Cancel(); + iRetryTimer->Cancel(); + IPTVLOGSTRING_LOW_LEVEL( + "MPX My Videos UI # RunL # iRefreshTimer stop" ); + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RunError() +// From CActive +// ----------------------------------------------------------------------------- +// +TInt CVcxHgMyVideosVideoDataUpdater::RunError( TInt aError ) + { + IPTVLOGSTRING2_LOW_LEVEL( "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater::RunError, aError = %d", aError ); + + if ( aError != KErrNone ) + { + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::DoCancel() +// From CActive +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::DoCancel() + { + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::CheckDrmL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::CheckDrmL( CVcxHgMyVideosVideoData& aVideoData ) + { + CMPXMedia* media = iVideoArray.MPXMediaByMPXItemId( aVideoData.MPXItemId() ); + if ( media && media->IsSupported( KMPXMediaGeneralUri ) ) + { + TUint32 flags = 0; + if ( media->IsSupported( KMPXMediaGeneralFlags ) ) + { + flags = media->ValueTObjectL( KMPXMediaGeneralFlags ); + } + if ( flags & EVcxMyVideosVideoDrmProtected ) + { + aVideoData.SetDrmProtected( ETrue ); + aVideoData.SetValidDrmRights( EFalse ); + + ContentAccess::CData* cData = CData::NewLC( + (TVirtualPathPtr) media->ValueText( KMPXMediaGeneralUri ), + EPeek, + EContentShareReadWrite ); + TInt intentResult = cData->EvaluateIntent( ContentAccess::EPlay ); + + // Not valid rights should return KErrCANoRights, KErrCANoPermission, + // or in rare cases KErrCAPendingRights. But we don't trust those and + // just compare against KErrNone. + if ( intentResult == KErrNone ) + { + aVideoData.SetValidDrmRights( ETrue ); + } + CleanupStack::PopAndDestroy( cData ); + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::GetActiveRequestCount() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::GetActiveRequestCount( + TInt& aPeekRequests, TInt& aGetRequests ) + { + aPeekRequests = 0; + aGetRequests = 0; + TInt count = iFetchArray.Count(); + for( TInt i = 0; i < count; ++i ) + { + CVcxHgMyVideosVideoData::TVideoDataState state = iFetchArray[i]->State(); + if ( state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekStarted ) + { + ++aPeekRequests; + } + else if ( state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailStarted ) + { + ++aGetRequests; + } + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::StartThumbnailL() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::StartThumbnailL( + CVcxHgMyVideosVideoData& aItem, TBool aPeek ) + { + CMPXMedia* media = iVideoArray.MPXMediaByMPXItemId( aItem.MPXItemId() ); + if ( media && media->IsSupported( KMPXMediaGeneralUri ) ) + { + TPtrC uri = media->ValueText( KMPXMediaGeneralUri ); + TPtrC mime = media->IsSupported( KMPXMediaGeneralMimeType ) ? + media->ValueText( KMPXMediaGeneralMimeType ) : KNullDesC; + TThumbnailRequestId id = 0; + if ( aPeek ) + { + CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC( + uri, mime ); + id = iModel.ThumbnailManager().PeekL( *source ); + CleanupStack::PopAndDestroy( source ); + } + else + { + CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC( + uri, mime ); + id = iModel.ThumbnailManager().GetL( *source ); + CleanupStack::PopAndDestroy( source ); + } + aItem.SetThumbnailConversionId( id ); + + IPTVLOGSTRING4_LOW_LEVEL( + "MPX My Videos UI # StartThumbnailL() called thumbID %d for %S (peek %d)", + aItem.ThumbnailConversionId(), + &media->ValueText( KMPXMediaGeneralUri ), + aPeek ); + + aItem.SetState( aPeek ? + CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekStarted : + CVcxHgMyVideosVideoData::EVideoDataStateThumbnailStarted ); + } + else + { + User::Leave( KErrNotFound ); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::TrySelectL() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::TrySelectL( TInt aIndex, + TBool aSelectForPeekOnly ) + { + // Move selected index to first index of the fetch array + TBool selected = EFalse; + CVcxHgMyVideosVideoData* item = iFetchArray[aIndex]; + CVcxHgMyVideosVideoData::TVideoDataState state = item->State(); + if ( aSelectForPeekOnly ) + { + // Accept item only for peeking + if ( state == CVcxHgMyVideosVideoData::EVideoDataStateNone ) + { + iFetchArray.InsertL( item, 0 ); + iFetchArray.Remove( aIndex + 1 ); + selected = ETrue; + } + } + else if ( state == CVcxHgMyVideosVideoData::EVideoDataStateNone || + state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekFinished ) + { + // Accept any item that waits to be fetched + iFetchArray.InsertL( item, 0 ); + iFetchArray.Remove( aIndex + 1 ); + selected = ETrue; + } + return selected; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::TrySelectFromScrollerL() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::TrySelectFromScrollerL( + TInt aPos, TBool aSelectForPeekOnly ) + { + TBool selected = EFalse; + CGulIcon* icon = iScroller.ItemL( aPos ).Icon(); + TMPXItemId mpxItemId = iVideoArray.ArrayIndexToMpxItemIdL( aPos ); + TInt index = IndexByMPXItemId( mpxItemId ); + if ( index >= 0 ) + { + // Skip fetch selection if icon already exist + if ( !icon ) + { + if ( TrySelectL( index, aSelectForPeekOnly ) ) + { + selected = ETrue; + } + } + else + { + iFetchArray[index]->SetState( + CVcxHgMyVideosVideoData::EVideoDataStateThumbnailFinished ); + StartFinalActions(); + } + } + return selected; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::TrySelectFromScrollerAreaL() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::TrySelectFromScrollerAreaL( + TInt aStartPos, TInt aEndPos, TBool aSelectForPeekOnly ) + { + TBool selected = EFalse; + if ( aEndPos >= aStartPos ) + { + // Search forwards + for ( TInt i = aStartPos; i <= aEndPos; i++ ) + { + if ( TrySelectFromScrollerL( i, aSelectForPeekOnly ) ) + { + selected = ETrue; + break; + } + } + } + else + { + // Search backwards + for ( TInt i = aStartPos; i >= aEndPos; i-- ) + { + if ( TrySelectFromScrollerL( i, aSelectForPeekOnly ) ) + { + selected = ETrue; + break; + } + } + } + return selected; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::StartFinalActions() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::StartFinalActions() + { + if ( !IsActive() ) + { + SetActive(); + TRequestStatus* stat = &iStatus; + User::RequestComplete( stat, KErrNone ); + } + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::CancelNeeded() +// ----------------------------------------------------------------------------- +// +TBool CVcxHgMyVideosVideoDataUpdater::CancelNeeded( CVcxHgMyVideosVideoData& aItem ) + { + CVcxHgMyVideosVideoData::TVideoDataState state = aItem.State(); + return ( state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailPeekStarted || + state == CVcxHgMyVideosVideoData::EVideoDataStateThumbnailStarted ); + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::RetryTimerCallBack() +// ----------------------------------------------------------------------------- +// +TInt CVcxHgMyVideosVideoDataUpdater::RetryTimerCallBack( TAny* aAny ) + { + CVcxHgMyVideosVideoDataUpdater* self = static_cast( aAny ); + self->iRetryTimer->Cancel(); + TRAPD( err, self->ContinueVideoDataFetchingL() ); + if ( err != KErrNone ) + { + IPTVLOGSTRING2_LOW_LEVEL( + "MPX My Videos UI # CVcxHgMyVideosVideoDataUpdater::RetryTimerCallBack, err = %d", + err ); + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CVcxHgMyVideosVideoDataUpdater::GetScrollerArea() +// ----------------------------------------------------------------------------- +// +void CVcxHgMyVideosVideoDataUpdater::GetScrollerArea( TInt& aFirstIndexOnScreen, + TInt& aLastIndexOnScreen, + TInt& aLastIndex ) + { + aLastIndex = Max( iScroller.ItemCount() - 1, 0 ); + aFirstIndexOnScreen = Max( iScroller.FirstIndexOnScreen(), 0 ); + aLastIndexOnScreen = Min( aFirstIndexOnScreen + iScroller.ItemsOnScreen(), aLastIndex ); + }