--- /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 <mpxmediaarray.h>
+#include <mpxmedia.h>
+#include <mpxmediageneraldefs.h>
+
+#include <ganes/HgScroller.h>
+#include <ganes/HgItem.h>
+
+#include <thumbnailmanager.h>
+#include <thumbnailmanagerobserver.h>
+#include <thumbnailobjectsource.h>
+#include <thumbnaildata.h>
+#include <DRMCommon.h> // DRM
+#include <gulicon.h>
+
+#include "IptvDebug.h"
+#include <myvideosindicator.h>
+#include <vcxmyvideosdefs.h>
+#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<TUint32>( 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<CVcxHgMyVideosVideoDataUpdater*>( 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<TUint32>( 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<CVcxHgMyVideosVideoDataUpdater*>( 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 );
+ }