mpx/collectionframework/collectionutility/src/mpxcollectionopenutility.cpp
changeset 0 a2952bb97e68
child 54 fa0adf088850
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Incremental OpenL() utility
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <mpxmessage.h>
       
    21 #include <mpxcollectionpath.h>
       
    22 #include <mpxcollectionutility.h>
       
    23 #include <mpxcollectionmessagedefs.h>
       
    24 #include <mpxmessagegeneraldefs.h>
       
    25 #include <mpxmediageneraldefs.h>
       
    26 #include <mpxcommandgeneraldefs.h>
       
    27 #include <mpxincrementalopendefs.h>
       
    28 #include <mpxmediacontainerdefs.h>
       
    29 #include <mpxcollectionmessage.h>
       
    30 #include <mpxlog.h>
       
    31 #include <mpxcollectionopenlresultdef.h>
       
    32 #include <mpxcollectioncommanddefs.h>
       
    33 #include "mpxcollectionopenutility.h"
       
    34 #include <e32math.h>
       
    35 
       
    36 // CONSTANTS
       
    37 const TInt KArrayGranularity = 5;
       
    38 
       
    39 // ---------------------------------------------------------------------------
       
    40 // static function to compare two datablock items
       
    41 // used for sorting datablocks
       
    42 // ---------------------------------------------------------------------------
       
    43 //
       
    44 static TInt CompareAsc( const TMPXOpenDataBlock& aFirst,
       
    45                         const TMPXOpenDataBlock& aSecond )
       
    46     {
       
    47     return aFirst.iOffset > aSecond.iOffset;
       
    48     }
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // static function to compare two datablock items
       
    52 // used for sorting datablocks
       
    53 // ---------------------------------------------------------------------------
       
    54 //
       
    55 static TInt CompareDsc( const TMPXOpenDataBlock& aFirst,
       
    56                         const TMPXOpenDataBlock& aSecond )
       
    57     {
       
    58     return aFirst.iOffset < aSecond.iOffset;
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // Constructor
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 CMPXCollectionOpenUtility::CMPXCollectionOpenUtility( MMPXCollectionObserver* aObs,
       
    66                                                       TUid aMode ) 
       
    67                                                     : iFetchStep(EFetchNone),
       
    68                                                       iObs( aObs ),
       
    69                                                       iIncrementalChunks(KArrayGranularity),
       
    70                                                       iMode( aMode )
       
    71                                                       
       
    72     {
       
    73     }
       
    74 
       
    75 
       
    76 // ---------------------------------------------------------------------------
       
    77 // 2nd Phase Constructor
       
    78 // ---------------------------------------------------------------------------
       
    79 //
       
    80 void CMPXCollectionOpenUtility::ConstructL()
       
    81     {
       
    82     iTimer = CPeriodic::NewL( CActive::EPriorityStandard );
       
    83     }
       
    84 
       
    85 
       
    86 // ---------------------------------------------------------------------------
       
    87 // Two-Phased Constructor
       
    88 // ---------------------------------------------------------------------------
       
    89 //
       
    90 EXPORT_C CMPXCollectionOpenUtility* CMPXCollectionOpenUtility::NewL( 
       
    91                                                  MMPXCollectionObserver* aObs,  
       
    92                                                  TUid aMode )
       
    93     {
       
    94     CMPXCollectionOpenUtility* self = 
       
    95                        new( ELeave ) CMPXCollectionOpenUtility( aObs, aMode );
       
    96     CleanupStack::PushL( self );
       
    97     self->ConstructL();
       
    98     CleanupStack::Pop( self );
       
    99     return self;
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // Destructor
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 CMPXCollectionOpenUtility::~CMPXCollectionOpenUtility()
       
   107     {
       
   108     if( iCollection )
       
   109       {
       
   110       iCollection->Close();
       
   111       }
       
   112     
       
   113     if( iTimer )
       
   114         {
       
   115         iTimer->Cancel();
       
   116         delete iTimer;
       
   117         }
       
   118     
       
   119     iIncrementalChunks.Close();
       
   120     delete iPath;
       
   121     delete iMedia;
       
   122     }
       
   123 
       
   124 // ---------------------------------------------------------------------------
       
   125 // Start the incremental fetching operation
       
   126 // ---------------------------------------------------------------------------
       
   127 //
       
   128 EXPORT_C void CMPXCollectionOpenUtility::StartL( TArray<TMPXAttribute> /*aAttrs*/,
       
   129                                                  TInt aChunkSize,
       
   130                                                  TInt aOffset,
       
   131                                                  TDirection aDirection,
       
   132                                                  TMPXAttribute aKeyAttribute )
       
   133     {
       
   134     // Assert we are idle
       
   135     ASSERT( iFetchStep == EFetchNone );
       
   136     MPX_DEBUG1("CMPXCollectionOpenUtility::StartL <---");
       
   137     // Copy the operation data
       
   138     iFetchInfo.iSize = aChunkSize;
       
   139     iFetchInfo.iOffset = aOffset;
       
   140     iFetchDirection = aDirection;
       
   141     iKeyAttribute = aKeyAttribute;
       
   142     iData = NULL;
       
   143     delete iMedia;
       
   144     iMedia = NULL;
       
   145     delete iPath; 
       
   146     iPath = NULL;
       
   147     // Start reading
       
   148     iFetchStep = EFetchCount;
       
   149     RunNext();
       
   150     MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->");
       
   151     }
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // Start the incremental fetching operation
       
   155 // ---------------------------------------------------------------------------
       
   156 //
       
   157 EXPORT_C void CMPXCollectionOpenUtility::StartL( const CMPXCollectionPath& aPath,
       
   158                                                  TArray<TMPXAttribute> /*aAttrs*/,
       
   159                                                  TInt aChunkSize,
       
   160                                                  TInt aOffset,
       
   161                                                  TDirection aDirection,
       
   162                                                  TMPXAttribute aKeyAttribute )
       
   163     {
       
   164     // Assert we are idle and isolated mode
       
   165     MPX_ASSERT( iFetchStep == EFetchNone );
       
   166     MPX_ASSERT( iMode == KMcModeIsolated || iMode == KMcModePlaylist );
       
   167     MPX_DEBUG1("CMPXCollectionOpenUtility::StartL aPath <---");
       
   168     if( !iCollection )
       
   169         {
       
   170         iCollection = MMPXCollectionUtility::NewL( this, iMode ); 
       
   171         }
       
   172     
       
   173     // Copy the operation data
       
   174     MPX_DEBUG_PATH( aPath );
       
   175     iFetchInfo.iSize = aChunkSize;
       
   176     iFetchInfo.iOffset = aOffset;
       
   177     iFetchDirection = aDirection;
       
   178     iKeyAttribute = aKeyAttribute;
       
   179     iData = NULL;
       
   180     delete iMedia;
       
   181     iMedia = NULL;
       
   182     
       
   183     delete iPath;
       
   184     iPath = NULL;
       
   185     iPath = CMPXCollectionPath::NewL( aPath );
       
   186     
       
   187     // Start the fetch operation by setting up the context
       
   188     // to the correct path
       
   189     //
       
   190     iFetchStep = EFetchPath;
       
   191     RunNext();
       
   192     
       
   193     MPX_DEBUG1("CMPXCollectionOpenUtility::StartL --->");
       
   194     }
       
   195 
       
   196 // ---------------------------------------------------------------------------
       
   197 // Stop the incremental fetching operation
       
   198 // ---------------------------------------------------------------------------
       
   199 //
       
   200 EXPORT_C void CMPXCollectionOpenUtility::Stop()
       
   201     {
       
   202     // Cancel all outstanding collection open requests
       
   203     MPX_DEBUG1("CMPXCollectionOpenUtility::Stop <---");
       
   204     if( iCollection )
       
   205         {
       
   206         iCollection->Collection().CancelRequest();
       
   207         }
       
   208     iTimer->Cancel();
       
   209     iIncrementalChunks.Reset();
       
   210     delete iMedia; 
       
   211     iMedia = NULL;
       
   212     iData = NULL;
       
   213     iFetchStep = EFetchNone;
       
   214     MPX_DEBUG1("CMPXCollectionOpenUtility::Stop --->");
       
   215     }
       
   216 
       
   217 // ---------------------------------------------------------------------------
       
   218 // Set the direction of the incremental fetching algorithm
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 EXPORT_C void CMPXCollectionOpenUtility::SetDirection( TDirection aDirection )
       
   222     {
       
   223     iFetchDirection = aDirection;
       
   224     
       
   225     if( iFetchStep == EFetchItems || iFetchStep == EFetchCommand )
       
   226         {
       
   227         TBool skipFirst = iFetchStep == EFetchCommand ? ETrue : EFalse;
       
   228         
       
   229         if( iFetchDirection == EFetchDown )
       
   230             {
       
   231             DoSortAscend( skipFirst );
       
   232             }
       
   233         else if( iFetchDirection == EFetchUp )
       
   234             {
       
   235             DoSortDescend( skipFirst );
       
   236             }
       
   237         else if( iFetchDirection == EFetchNormal )
       
   238             {
       
   239             TRAP_IGNORE( DoSortNormalL( skipFirst ) );
       
   240             }
       
   241         }
       
   242     }
       
   243 
       
   244 // ---------------------------------------------------------------------------
       
   245 // Set the fetching delay
       
   246 // ---------------------------------------------------------------------------
       
   247 //
       
   248 EXPORT_C void CMPXCollectionOpenUtility::SetDelay( TInt aDelay )
       
   249     {
       
   250     iFetchDelay = aDelay;
       
   251     }
       
   252 
       
   253 // ---------------------------------------------------------------------------
       
   254 // Get the current path
       
   255 // ---------------------------------------------------------------------------
       
   256 //
       
   257 EXPORT_C CMPXCollectionPath* CMPXCollectionOpenUtility::PathL()
       
   258     {
       
   259     CMPXCollectionPath* p(NULL);
       
   260     
       
   261     if( iCollection )
       
   262         {
       
   263         p = iCollection->Collection().PathL();
       
   264         }
       
   265     return p;
       
   266     }
       
   267     
       
   268 // ---------------------------------------------------------------------------
       
   269 // Handle Collection Message
       
   270 // ---------------------------------------------------------------------------
       
   271 //
       
   272 void CMPXCollectionOpenUtility::HandleCollectionMessage(CMPXMessage* aMsg, TInt aErr)
       
   273     {
       
   274     if( aErr == KErrNone && aMsg )
       
   275         {
       
   276         TRAP_IGNORE( DoHandleCollectionMessageL( *aMsg ) );
       
   277         }
       
   278     }
       
   279 
       
   280  // ---------------------------------------------------------------------------
       
   281  // HandleOpenL
       
   282  // ---------------------------------------------------------------------------
       
   283  //
       
   284 void CMPXCollectionOpenUtility::HandleOpenL(const CMPXMedia& aEntries,
       
   285                                             TInt aIndex,
       
   286                                             TBool aComplete,
       
   287                                             TInt aError)
       
   288     {
       
   289     if( iFetchStep == EFetchCount )
       
   290         {
       
   291         DoHandleCountL( aEntries, aIndex, aError );
       
   292         }
       
   293     else if( iFetchStep == EFetchItems )
       
   294         {
       
   295         DoHandleFetchItemsL( aEntries, aIndex, aError );
       
   296         }
       
   297     else
       
   298         {
       
   299         MPX_DEBUG1("CMPXCollectionOpenUtility::HandleOpenL EFetchPath/EFetchNone");
       
   300         iFetchStep = EFetchNone;
       
   301         iObs->HandleOpenL( aEntries, aIndex, aComplete, aError );
       
   302         }
       
   303     }
       
   304  
       
   305  // ---------------------------------------------------------------------------
       
   306  // HandleOpenL
       
   307  // ---------------------------------------------------------------------------
       
   308  //
       
   309 void CMPXCollectionOpenUtility::HandleOpenL(const CMPXCollectionPlaylist& aPlaylist,
       
   310                                             TInt aError)
       
   311     {
       
   312     iObs->HandleOpenL( aPlaylist, aError );
       
   313     }
       
   314  
       
   315  // ---------------------------------------------------------------------------
       
   316  // Handle Command Complete
       
   317  // ---------------------------------------------------------------------------
       
   318  //
       
   319 void CMPXCollectionOpenUtility::HandleCommandComplete(CMPXCommand* aCommandResult, 
       
   320                                                       TInt aError )
       
   321     {
       
   322     // Continue fetching items
       
   323     iFetchStep = EFetchItems;
       
   324     TRAP_IGNORE( DoHandleCommandCompleteL( *aCommandResult, aError ) );
       
   325     }
       
   326  
       
   327  // ---------------------------------------------------------------------------
       
   328  // Handle Collection Media
       
   329  // ---------------------------------------------------------------------------
       
   330  //
       
   331 void CMPXCollectionOpenUtility::HandleCollectionMediaL(const CMPXMedia& /*aMedia*/, 
       
   332                                                        TInt /*aError*/)
       
   333     {
       
   334     // Do Nothing
       
   335     }
       
   336 
       
   337 // ---------------------------------------------------------------------------
       
   338 // Handle Collection Messages
       
   339 // ---------------------------------------------------------------------------
       
   340 //
       
   341 void CMPXCollectionOpenUtility::DoHandleCollectionMessageL( const CMPXMessage& aMsg )
       
   342     {
       
   343     TMPXMessageId id( aMsg.ValueTObjectL<TMPXMessageId>( KMPXMessageGeneralId ) );
       
   344     if ( KMPXMessageGeneral == id &&
       
   345          iFetchStep == EFetchPath )
       
   346         {
       
   347         TInt event( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralEvent ) );
       
   348         TInt type( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralType ) );
       
   349         TInt data( aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralData) );
       
   350         if ( event == TMPXCollectionMessage::EPathChanged && 
       
   351             type == EMcPathChangedByOpen )
       
   352             {
       
   353             MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCollectionMessageL -- path opened");
       
   354             
       
   355             if( data == EMcContainerOpened)
       
   356                 {
       
   357                 iFetchStep = EFetchCount;
       
   358                 RunNext();
       
   359                 }
       
   360             else if( data == EMcItemOpened )  // only 2 cases
       
   361                 {
       
   362                 // Playlist, simply forward back to the observer
       
   363                 iCollection->Collection().OpenL();
       
   364                 iFetchStep = EFetchNone;
       
   365                 }
       
   366             }
       
   367         }
       
   368     }
       
   369 
       
   370 // ---------------------------------------------------------------------------
       
   371 // Handle Command complete
       
   372 // ---------------------------------------------------------------------------
       
   373 //
       
   374 void CMPXCollectionOpenUtility::DoHandleCommandCompleteL(CMPXCommand& /*aCommandResult*/, 
       
   375                                                          TInt aError)
       
   376     {
       
   377     if( iSelecting )
       
   378         {
       
   379         iSelecting = EFalse;
       
   380         }
       
   381     else if( aError == KErrNone )
       
   382         {
       
   383         // Get the data to return to the client, callback at HandleOpen()
       
   384         //
       
   385         // Implemented because the command tells the plugin to fetch the 
       
   386         // next block of data. However, the actual media object containing 
       
   387         // the current browse data may have been re-allocated. We cannot
       
   388         // assume that the data pointer remains the same. Therefore, it is
       
   389         // safer to refetch the data from the collection via OpenL()
       
   390         // This call should be FAST because the data has already been read at this point
       
   391         // 
       
   392         MPX_DEBUG1("CMPXCollectionOpenUtility::HandleCommandComplete OpenL <---");
       
   393         if( iIncrementalChunks.Count() == 1 || iFirstOpen )
       
   394             {
       
   395             DoSelectIndexL();
       
   396             }
       
   397         iCollection->Collection().OpenL();
       
   398         }
       
   399     else if( aError == KErrNotReady )
       
   400         {
       
   401         // Cache was deleted, need to restart the fetching operation
       
   402         Stop();
       
   403         iFetchStep = EFetchCount;
       
   404         iCollection->Collection().OpenL();
       
   405         }
       
   406     else // aError != KErrNone 
       
   407         {
       
   408         // Error occured, such as not supported
       
   409         MPX_DEBUG2("CMPXCollectionOpenUtility::HandleCommandComplete Error %i <---", aError);
       
   410         iFetchStep = EFetchNone;
       
   411         
       
   412         CMPXMedia* temp = CMPXMedia::NewL();
       
   413         CleanupStack::PushL( temp );    
       
   414         iObs->HandleOpenL( *temp, 0, ETrue, aError );
       
   415         CleanupStack::PopAndDestroy( temp );
       
   416         }    
       
   417     }
       
   418 
       
   419 // ---------------------------------------------------------------------------
       
   420 // Fetch count step
       
   421 // ---------------------------------------------------------------------------
       
   422 //
       
   423 void CMPXCollectionOpenUtility::DoFetchCountL()
       
   424     {
       
   425     if( !iCollection )
       
   426         {
       
   427         iCollection = MMPXCollectionUtility::NewL( this, iMode ); 
       
   428         }
       
   429     
       
   430     // Ask for the total item count
       
   431     // Cache current iPath
       
   432     delete iPath;
       
   433     iPath = NULL;
       
   434     iPath = iCollection->Collection().PathL();
       
   435     
       
   436     iCollection->Collection().OpenL();
       
   437     }
       
   438 
       
   439 // ---------------------------------------------------------------------------
       
   440 // Handle the count step
       
   441 // ---------------------------------------------------------------------------
       
   442 //
       
   443 void CMPXCollectionOpenUtility::DoHandleCountL(const CMPXMedia& aEntries, 
       
   444                                                TInt aIndex,
       
   445                                                TInt aError)
       
   446     {
       
   447     ASSERT( iFetchStep == EFetchCount );
       
   448     
       
   449     MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL error %i <---", aError);
       
   450     TBool done(EFalse);
       
   451     if( aError == KErrNone )
       
   452         {
       
   453         // Do we support incremental for this OpenL()?
       
   454         //
       
   455         TBool supportIncremental(EFalse);
       
   456         if( aEntries.IsSupported( KMPXCollectionOpenLSupportsIncremental ) )
       
   457             {
       
   458             supportIncremental = aEntries.ValueTObjectL<TBool>( 
       
   459                                         KMPXCollectionOpenLSupportsIncremental );
       
   460             }
       
   461         
       
   462         if( supportIncremental )
       
   463             {
       
   464             TInt count(0);
       
   465             if( aEntries.IsSupported(KMPXMediaArrayCount) )
       
   466                 {
       
   467                 count = aEntries.ValueTObjectL<TInt>(KMPXMediaArrayCount);
       
   468                 }
       
   469             
       
   470             if( iFetchInfo.iOffset == KErrNotFound )
       
   471                 {
       
   472                 // If the client did not specify an offset
       
   473                 // we use the index the collection is pointing to
       
   474                 // as the starting offset
       
   475                 //
       
   476                 iFetchInfo.iOffset = aIndex;
       
   477                 }
       
   478             if( count > 0 )
       
   479                 {
       
   480                 // Perform the chunking here
       
   481                 DoSetupChunksL( count );
       
   482                 DoCompactTaskListL( aEntries );
       
   483                 
       
   484                 MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleCountL count %i", iIncrementalChunks.Count() );
       
   485                 if( iIncrementalChunks.Count() )
       
   486                     {
       
   487                     // Start running the fetching algorithm
       
   488                     iFetchStep = EFetchItems; 
       
   489                     iFirstOpen = ETrue;
       
   490                     
       
   491                     // Sync up the path, as there could have been items deleted
       
   492                     delete iPath;
       
   493                     iPath = NULL;
       
   494                     iPath = iCollection->Collection().PathL();
       
   495                     
       
   496                     if( iObs )
       
   497                         {
       
   498                         iObs->HandleOpenL( aEntries, aIndex, EFalse, aError );
       
   499                         }
       
   500                     RunNext();
       
   501                     }
       
   502                 else 
       
   503                     {
       
   504                     // Update index before returning
       
   505                     DoSelectIndexL();
       
   506                     iFetchStep = EFetchNone;
       
   507                     iCollection->Collection().OpenL();
       
   508                     done = EFalse;
       
   509                     }     
       
   510                 }
       
   511             else
       
   512                 {
       
   513                 done = ETrue;
       
   514                 }    
       
   515             }
       
   516         else // !supportIncremental
       
   517             {
       
   518             // Just return the results
       
   519             //
       
   520             MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleCountL incremental not supported");
       
   521             done = ETrue;    
       
   522             }        
       
   523         
       
   524         }
       
   525     if( (aError != KErrNone) || done )
       
   526         {
       
   527         // Stop the OpenL() operation
       
   528         iFetchStep = EFetchNone;
       
   529         if( iObs )
       
   530             {
       
   531             iObs->HandleOpenL( aEntries, aIndex, ETrue, aError );
       
   532             }
       
   533         }
       
   534     }
       
   535 
       
   536 // ---------------------------------------------------------------------------
       
   537 // Fetch items step
       
   538 // ---------------------------------------------------------------------------
       
   539 //
       
   540 void CMPXCollectionOpenUtility::DoFetchItemsL()
       
   541     {
       
   542     // Construct a command to fetch the next chunk
       
   543     //
       
   544     MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL <---" );
       
   545     if( iIncrementalChunks.Count() > 0 )
       
   546         {
       
   547         CMPXCommand* command = CMPXCommand::NewL();
       
   548         CleanupStack::PushL( command );
       
   549     
       
   550         // Construct the command
       
   551         //
       
   552         TInt colId( iPath->Id(0) );
       
   553         TInt offset( iIncrementalChunks[0].iOffset );
       
   554         command->SetTObjectValueL( KMPXCommandGeneralId,
       
   555                                    KMPXCommandIdIncrementalOpenL );
       
   556         command->SetTObjectValueL( KMPXCommandGeneralCollectionId,
       
   557                                    colId );
       
   558         command->SetCObjectValueL(KMPXCollectionCommandIdIncOpenLPath,iPath );
       
   559         command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLOffset, 
       
   560                                   offset );
       
   561         command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLNumItems, iFetchInfo.iSize);
       
   562         
       
   563         // If some partial data is available
       
   564         // try to optimize this by using the ascending or decending keys
       
   565         //
       
   566         if( iData )
       
   567             {
       
   568             if( offset-1 > 0 && offset-1 < iData->Count() &&
       
   569                 iData->AtL(offset-1)->IsSupported(iKeyAttribute) )
       
   570                 {
       
   571                 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadAscending);
       
   572                 const TDesC& key = iData->AtL(offset-1)->ValueText(iKeyAttribute);
       
   573                 command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key);
       
   574                 }
       
   575             else if( offset+iFetchInfo.iSize < iData->Count() &&
       
   576                      iData->AtL(offset+iFetchInfo.iSize)->IsSupported(iKeyAttribute) )
       
   577                 {
       
   578                 command->SetTObjectValueL(KMPXCollectionCommandIdIncOpenLAscDsc, EReadDescending);
       
   579                 const TDesC& key = iData->AtL(offset+iFetchInfo.iSize)->ValueText(iKeyAttribute);
       
   580                 command->SetTextValueL(KMPXCollectionCommandIdIncOpenLKeyItem,key);
       
   581                 }
       
   582             }
       
   583         
       
   584         // Command sent to the collection, callback HandleCommandComplete()
       
   585         //
       
   586         MPX_DEBUG2("CMPXCollectionOpenUtility::DoFetchItemsL offset %i <---", offset );
       
   587         iFetchStep = EFetchCommand;
       
   588         iCollection->Collection().CommandL( *command );
       
   589         CleanupStack::PopAndDestroy( command );
       
   590         }
       
   591     MPX_DEBUG1("CMPXCollectionOpenUtility::DoFetchItemsL --->" );
       
   592     }
       
   593 
       
   594 // ---------------------------------------------------------------------------
       
   595 // Handle Completion of fetch items step
       
   596 // ---------------------------------------------------------------------------
       
   597 //  
       
   598 void CMPXCollectionOpenUtility::DoHandleFetchItemsL( const CMPXMedia& aEntries,
       
   599                                                      TInt aIndex, 
       
   600                                                      TInt aError )
       
   601     {
       
   602     MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL <---" ); 
       
   603     // Task is done, and compact the list
       
   604     //
       
   605     TInt curOffset(0);
       
   606     if( iIncrementalChunks.Count() )
       
   607         {
       
   608         curOffset = iIncrementalChunks[0].iOffset;
       
   609         iIncrementalChunks.Remove(0);
       
   610         DoCompactTaskListL( aEntries );
       
   611         }
       
   612     else
       
   613         {
       
   614         MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL No more chunks" ); 
       
   615         }
       
   616         
       
   617     TBool complete = iIncrementalChunks.Count() == 0 ? ETrue : EFalse;
       
   618     
       
   619     // Keep a reference here 
       
   620     //
       
   621     delete iMedia;
       
   622     iMedia = NULL;
       
   623     iMedia = CMPXMedia::NewL( aEntries );
       
   624     iData = NULL;
       
   625     if( aEntries.IsSupported( KMPXMediaArrayContents ) )
       
   626         {
       
   627         iData = aEntries.Value<CMPXMediaArray>( KMPXMediaArrayContents );
       
   628         User::LeaveIfNull(iData);
       
   629         }
       
   630     
       
   631     // Run the next step of the fetching algorithm
       
   632     // Do not run if stopped
       
   633     //
       
   634     TInt count(iIncrementalChunks.Count());
       
   635     if( count != 0 && iFetchStep != EFetchNone )   
       
   636         {
       
   637         // Update the path, as the item IDs will be filled
       
   638         //
       
   639         MPX_DEBUG2("CMPXCollectionOpenUtility::DoHandleFetchItemsL run next %i", count ); 
       
   640         delete iPath;
       
   641         iPath = NULL;
       
   642         iPath = iCollection->Collection().PathL();
       
   643     
       
   644         // Command to fetch next chunk
       
   645         //
       
   646         RunNext();
       
   647         }
       
   648     else
       
   649         {
       
   650         // All done
       
   651         iFetchStep = EFetchNone;
       
   652         }
       
   653 
       
   654     // Callback to observer with some treshold to avoid over redrawing
       
   655     // Playlists need every handle open to update the path
       
   656     //
       
   657     if( iObs && 
       
   658         (Abs<TInt>(aIndex-curOffset) < iFetchInfo.iSize ||
       
   659         iFirstOpen || iMode == KMcModePlaylist || complete ) )
       
   660         {
       
   661         iFirstOpen = EFalse;
       
   662         MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL callback" ); 
       
   663         iObs->HandleOpenL( aEntries, aIndex, complete, aError );
       
   664         }
       
   665     
       
   666     MPX_DEBUG1("CMPXCollectionOpenUtility::DoHandleFetchItemsL -->" );     
       
   667     }
       
   668 
       
   669 // ---------------------------------------------------------------------------
       
   670 // Run the next step
       
   671 // ---------------------------------------------------------------------------
       
   672 //    
       
   673 void CMPXCollectionOpenUtility::RunNext()
       
   674     {
       
   675     TCallBack cb( Callback,this );
       
   676     iTimer->Cancel();
       
   677     iTimer->Start( TTimeIntervalMicroSeconds32( iFetchDelay ),
       
   678                       TTimeIntervalMicroSeconds32( iFetchDelay ),
       
   679                       cb);
       
   680     }
       
   681 
       
   682 // ---------------------------------------------------------------------------
       
   683 // Set some callback
       
   684 // ---------------------------------------------------------------------------
       
   685 //
       
   686 TInt CMPXCollectionOpenUtility::Callback( TAny* aAny )
       
   687     {
       
   688     TRAP_IGNORE( ((CMPXCollectionOpenUtility*)aAny)->HandleCallbackL() );
       
   689     return ETrue;
       
   690     }
       
   691 
       
   692 // ---------------------------------------------------------------------------
       
   693 // HandleCallback from iTimer
       
   694 // ---------------------------------------------------------------------------
       
   695 //
       
   696 void CMPXCollectionOpenUtility::HandleCallbackL()
       
   697     {
       
   698     switch( iFetchStep )
       
   699         {
       
   700         case EFetchPath:
       
   701             {
       
   702             iCollection->Collection().OpenL( *iPath );
       
   703             break;
       
   704             }    
       
   705         case EFetchCount:
       
   706             {
       
   707             DoFetchCountL();
       
   708             break;
       
   709             }
       
   710         case EFetchItems:
       
   711             {
       
   712             DoFetchItemsL();
       
   713             break;
       
   714             }
       
   715         case EFetchNone:
       
   716             {
       
   717             break; // do nothing    
       
   718             }
       
   719         default:
       
   720             {
       
   721             MPX_ASSERT(0);
       
   722             break;
       
   723             }
       
   724         }
       
   725     // Run once only
       
   726     iTimer->Cancel();
       
   727     }
       
   728 
       
   729 // ---------------------------------------------------------------------------
       
   730 // Setup the chunks
       
   731 // ---------------------------------------------------------------------------
       
   732 // 
       
   733 void CMPXCollectionOpenUtility::DoSetupChunksL( TInt aCount )
       
   734     {
       
   735     // Number of chunks we are going to have
       
   736     // And the chunk the offset is going to be at
       
   737     //
       
   738     iIncrementalChunks.Reset();
       
   739     
       
   740     TInt numChunks(0);
       
   741     if( aCount > 0 )
       
   742         {
       
   743         // Truncate and add 1 if any modulus, no Ceil() function 
       
   744         numChunks = (TInt)aCount/iFetchInfo.iSize;
       
   745         if( aCount % iFetchInfo.iSize )
       
   746             {
       
   747             numChunks++;    
       
   748             }
       
   749         }
       
   750     TInt offSetChunk = (TInt) iFetchInfo.iOffset / iFetchInfo.iSize ;
       
   751     
       
   752     // First chunk
       
   753     TMPXOpenDataBlock chunk;
       
   754     chunk.iOffset = offSetChunk*iFetchInfo.iSize;
       
   755     chunk.iSize = iFetchInfo.iSize;
       
   756     iIncrementalChunks.AppendL( chunk );
       
   757     
       
   758     // Left and right of the first chunk
       
   759     TInt left = offSetChunk-1;
       
   760     TInt right = offSetChunk+1;
       
   761     TInt count(numChunks-1);
       
   762     while( count > 0 )
       
   763         {
       
   764         // Append Left Chunk
       
   765         //
       
   766         TInt temp(left);
       
   767         if( left < 0 )
       
   768             {
       
   769             // Wrap around to end of the list
       
   770             temp = numChunks + left;
       
   771             }
       
   772         chunk.iOffset = temp*iFetchInfo.iSize;
       
   773         iIncrementalChunks.AppendL( chunk );    
       
   774         MPX_DEBUG2("Adding Chunk %i", temp);
       
   775         
       
   776         count--;
       
   777         left--;
       
   778         
       
   779         // Append Right Chunk
       
   780         if( temp != right%numChunks )
       
   781             {
       
   782             chunk.iOffset = (right%numChunks)*iFetchInfo.iSize;
       
   783             iIncrementalChunks.AppendL( chunk );
       
   784             MPX_DEBUG2("Adding Chunk %i", right%numChunks);
       
   785             
       
   786             count--;
       
   787             right++;
       
   788             }
       
   789         }
       
   790     
       
   791     // Set the direction and re-order as necessary
       
   792     SetDirection( iFetchDirection );
       
   793     }
       
   794 
       
   795 // ---------------------------------------------------------------------------
       
   796 // Sort the internal array ascending
       
   797 // ---------------------------------------------------------------------------
       
   798 // 
       
   799 void CMPXCollectionOpenUtility::DoSortAscend( TBool aSkipFirst )
       
   800     {
       
   801     if( iIncrementalChunks.Count() > 0 )
       
   802         {
       
   803         TMPXOpenDataBlock tmp;
       
   804         if( aSkipFirst )
       
   805             {
       
   806             tmp = iIncrementalChunks[0];
       
   807             iIncrementalChunks.Remove(0);
       
   808             }
       
   809         iIncrementalChunks.Sort( CompareAsc );
       
   810         
       
   811         if( aSkipFirst )
       
   812             {
       
   813             iIncrementalChunks.Insert( tmp, 0 );    
       
   814             }
       
   815         }
       
   816     
       
   817 #ifdef _DEBUG
       
   818     TInt c=iIncrementalChunks.Count();
       
   819     for( TInt i=0; i<c; ++i )
       
   820         {
       
   821         MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset);
       
   822         }
       
   823 #endif // _DEBUG
       
   824     }
       
   825 
       
   826 // ---------------------------------------------------------------------------
       
   827 // Sort the internal array decending
       
   828 // ---------------------------------------------------------------------------
       
   829 // 
       
   830 void CMPXCollectionOpenUtility::DoSortDescend( TBool aSkipFirst )
       
   831     {
       
   832     if( iIncrementalChunks.Count() > 0 )
       
   833         {
       
   834         TMPXOpenDataBlock tmp;
       
   835         if( aSkipFirst )
       
   836             {
       
   837             tmp = iIncrementalChunks[0];
       
   838             iIncrementalChunks.Remove(0);
       
   839             }
       
   840         iIncrementalChunks.Sort( CompareDsc );
       
   841         
       
   842         if( aSkipFirst )
       
   843             {
       
   844             iIncrementalChunks.Insert( tmp, 0 );    
       
   845             }
       
   846         }
       
   847                
       
   848 #ifdef _DEBUG
       
   849     TInt c=iIncrementalChunks.Count();
       
   850     for( TInt i=0; i<c; ++i )
       
   851         {
       
   852         MPX_DEBUG2("Order %i", iIncrementalChunks[i].iOffset);
       
   853         }
       
   854 #endif // _DEBUG
       
   855     }
       
   856 
       
   857 // ---------------------------------------------------------------------------
       
   858 // Sort the internal array in normal form
       
   859 // ---------------------------------------------------------------------------
       
   860 // 
       
   861 void CMPXCollectionOpenUtility::DoSortNormalL( TBool aSkipFirst )
       
   862     {
       
   863     DoSortAscend( aSkipFirst );
       
   864     
       
   865     RArray<TMPXOpenDataBlock> temp;
       
   866     CleanupClosePushL( temp );
       
   867     
       
   868     TBool start = aSkipFirst ? 1:0;
       
   869     TInt count( iIncrementalChunks.Count() );
       
   870     TInt c(count);
       
   871     if( aSkipFirst )
       
   872         {
       
   873         temp.AppendL( iIncrementalChunks[0] );
       
   874         count--;    
       
   875         }
       
   876     
       
   877     TInt left(iIncrementalChunks.Count()/2);
       
   878     TInt right = left+1;
       
   879     while( count > 0)
       
   880         {
       
   881         if( left>=start )
       
   882             {
       
   883             temp.AppendL( iIncrementalChunks[left] );
       
   884             left--;
       
   885             count--;
       
   886             }
       
   887         if( right<c )
       
   888             {
       
   889             temp.AppendL( iIncrementalChunks[right] );
       
   890             right++;
       
   891             count--;
       
   892             }
       
   893         }
       
   894     
       
   895     // Copy the results
       
   896     iIncrementalChunks.Reset();
       
   897     c= temp.Count();
       
   898     for( TInt i=0; i<c; ++i )
       
   899         {
       
   900         iIncrementalChunks.AppendL( temp[i] );
       
   901         }
       
   902     CleanupStack::PopAndDestroy( &temp );
       
   903     }
       
   904 
       
   905 // ---------------------------------------------------------------------------
       
   906 // Compact the internal task list
       
   907 // ---------------------------------------------------------------------------
       
   908 // 
       
   909 void CMPXCollectionOpenUtility::DoCompactTaskListL( const CMPXMedia& aMedia )
       
   910     {
       
   911     RArray<TMPXOpenDataBlock> datablocks;
       
   912     CleanupClosePushL( datablocks );
       
   913     
       
   914     TInt c( iIncrementalChunks.Count() );
       
   915 
       
   916     if( aMedia.IsSupported(KMPXCollectionOpenLAllResultRange) )
       
   917         {
       
   918         // De-serialize from global data
       
   919         //
       
   920         const TDesC& buf = aMedia.ValueText(KMPXCollectionOpenLAllResultRange);
       
   921         CBufBase* buffer(NULL);
       
   922         MPXUser::CreateBufferL( buf, buffer );
       
   923         CleanupStack::PushL( buffer );
       
   924         ::CreateFromBufferL( *buffer, datablocks );
       
   925         CleanupStack::PopAndDestroy( buffer );
       
   926         
       
   927         // Remove un-necessary fetches
       
   928         TInt c2( datablocks.Count() );
       
   929         for( TInt i=c-1; i>=0; --i )
       
   930             {
       
   931             TMPXOpenDataBlock& chunk = iIncrementalChunks[i];
       
   932             for( TInt j=0; j<c2; ++j )
       
   933                 {
       
   934                 TMPXOpenDataBlock b = datablocks[j];
       
   935                 
       
   936                 if( chunk.iOffset >= b.iOffset && 
       
   937                     chunk.iOffset+chunk.iSize <= b.iOffset+b.iSize )
       
   938                     {
       
   939                     // Don't need to fetch what is already
       
   940                     // available
       
   941                     //
       
   942                     iIncrementalChunks.Remove( i );
       
   943                     break;
       
   944                     }
       
   945                 }
       
   946             }
       
   947         }
       
   948     
       
   949     CleanupStack::PopAndDestroy( &datablocks );    
       
   950     }
       
   951 
       
   952 // ---------------------------------------------------------------------------
       
   953 // Update the selection index
       
   954 // ---------------------------------------------------------------------------
       
   955 // 
       
   956 void CMPXCollectionOpenUtility::DoSelectIndexL()
       
   957     {
       
   958     CMPXCommand* command = CMPXCommand::NewL();
       
   959     CleanupStack::PushL( command );
       
   960 
       
   961     // Construct the command
       
   962     //
       
   963     command->SetTObjectValueL( KMPXCommandGeneralId,
       
   964                                KMPXCommandIdCollectionSelect );
       
   965     iCollection->Collection().CommandL( *command );
       
   966     iSelecting = ETrue;
       
   967     CleanupStack::PopAndDestroy( command );
       
   968     }
       
   969 // END OF FILE