mpx/collectionframework/collectionutility/src/mpxcollectionplaylist.cpp
changeset 0 a2952bb97e68
child 28 f56ec6ce2732
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2006 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:  implementation of collection playlist
       
    15 *
       
    16 */
       
    17 
       
    18 #include <e32math.h>
       
    19 #include <mpxcollectionpath.h>
       
    20 #include <mpxcmn.h>
       
    21 #include <mpxcollectionutility.h>
       
    22 #include <mpxcollectionmessage.h>
       
    23 #include <mpxmediageneraldefs.h>
       
    24 #include <mpxmessagegeneraldefs.h>
       
    25 #include <mpxmedia.h>
       
    26 #include <mpxmediaarray.h>
       
    27 #include <mpxmediacontainerdefs.h>
       
    28 #include <mpxlog.h>
       
    29 #include <mpxcommandgeneraldefs.h>
       
    30 #include <mpxcollectioncommanddefs.h>
       
    31 #include <mpxcollectionmessagedefs.h>
       
    32 #include <mpxmessagecontainerdefs.h>
       
    33 
       
    34 #include <mpxcollectionopenutility.h>
       
    35 
       
    36 #include "mpxcollectionplaylistobserver.h"
       
    37 #include "mpxcollectionplaylist.h"
       
    38 
       
    39 // CONSTANTS
       
    40 const TInt KIncrementalFetchSize = 400;
       
    41 const TInt KIncrementalDelay = 2000000;
       
    42 
       
    43 // -----------------------------------------------------------------------------
       
    44 // Two-phased constructor.
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL()
       
    48     {
       
    49     MPX_DEBUG1("-->CMPXCollectionPlaylist::NewL()"); 
       
    50     CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(NULL);
       
    51     CleanupStack::PushL(p);
       
    52     p->ConstructL();
       
    53     CleanupStack::Pop(p);
       
    54     MPX_DEBUG2("<--CMPXCollectionPlaylist::NewL() playlist 0x%08x", p);
       
    55     return p;
       
    56     }
       
    57 
       
    58 // -----------------------------------------------------------------------------
       
    59 // Two-phased constructor.
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
       
    63     const CMPXCollectionPlaylist& aPlaylist,
       
    64     MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
       
    65     {
       
    66     MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(pl, plobs) with plobs 0x%08x", aPlObs); 
       
    67     CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
       
    68     CleanupStack::PushL(p);
       
    69     p->ConstructL(aPlaylist);
       
    70     CleanupStack::Pop(p);
       
    71     MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
       
    72                p, aPlObs);  
       
    73     return p;
       
    74     }
       
    75     
       
    76 // -----------------------------------------------------------------------------
       
    77 // Two-phased constructor.
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
       
    81     const CMPXCollectionPath& aPath,
       
    82     MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
       
    83     {
       
    84     MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(path, plobs) with plobs 0x%08x", aPlObs); 
       
    85     CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
       
    86     CleanupStack::PushL(p);
       
    87     p->ConstructL(aPath);
       
    88     CleanupStack::Pop(p);
       
    89     MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
       
    90                p, aPlObs);  
       
    91     return p;
       
    92     }
       
    93     
       
    94 // -----------------------------------------------------------------------------
       
    95 // Two-phased constructor.
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
       
    99     RReadStream& aStream,
       
   100     MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
       
   101     {
       
   102     MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(strm, plobs) with plobs 0x%08x", aPlObs); 
       
   103     CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
       
   104     CleanupStack::PushL(p);
       
   105     p->ConstructL(aStream);
       
   106     CleanupStack::Pop(p);
       
   107     MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
       
   108                p, aPlObs);  
       
   109     return p;
       
   110     }
       
   111 
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // Default constructor
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 CMPXCollectionPlaylist::CMPXCollectionPlaylist(
       
   118     MMPXCollectionPlaylistObserver* aPlObs)
       
   119 :   iRepeatMode(ERepeatOff), iShuffle(EFalse), iRemote(EFalse), 
       
   120     iItemIndex(KErrNotFound),iEmbedded(EFalse), iPlObs(aPlObs),
       
   121     iRepeatEnabled(ETrue),
       
   122     iShuffleEnabled(ETrue), iAutoPlaylist(EFalse),
       
   123     iAutoPlay(ETrue), iSingleItemPlaylist(EFalse),
       
   124     iPreInitPlugin(ETrue)
       
   125     {
       
   126     }
       
   127     
       
   128 // ----------------------------------------------------------------------------
       
   129 // 2nd phase constructor. 
       
   130 // ----------------------------------------------------------------------------
       
   131 //
       
   132 void CMPXCollectionPlaylist::ConstructL(const CMPXCollectionPath& aPath)
       
   133     {
       
   134     MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aPath)");
       
   135     iPath=CMPXCollectionPath::NewL(aPath); 
       
   136     iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
       
   137     SetShuffleL(EFalse, EFalse);
       
   138     if (!iAutoPlaylist)
       
   139         {
       
   140         DoIncrementalOpenL();
       
   141         }
       
   142     }
       
   143     
       
   144 // ----------------------------------------------------------------------------
       
   145 // 2nd phase constructor. 
       
   146 // ----------------------------------------------------------------------------
       
   147 //
       
   148 void CMPXCollectionPlaylist::ConstructL(
       
   149     const CMPXCollectionPlaylist& aPlaylist)
       
   150     {
       
   151     MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aPlaylist)");
       
   152     iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
       
   153     CopyContentL(aPlaylist);
       
   154     }
       
   155 
       
   156 // ----------------------------------------------------------------------------
       
   157 // 2nd phase constructor. 
       
   158 // ----------------------------------------------------------------------------
       
   159 //
       
   160 void CMPXCollectionPlaylist::ConstructL(RReadStream& aStream)
       
   161     {
       
   162     MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aStream)");
       
   163     InternalizeL(aStream);
       
   164     iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
       
   165     if (!iAutoPlaylist)
       
   166         {
       
   167         DoIncrementalOpenL();
       
   168         }
       
   169     }
       
   170 
       
   171 // ----------------------------------------------------------------------------
       
   172 // 2nd phase constructor. 
       
   173 // ----------------------------------------------------------------------------
       
   174 //
       
   175 void CMPXCollectionPlaylist::ConstructL()
       
   176     {
       
   177     MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL()");
       
   178     iPath = CMPXCollectionPath::NewL();
       
   179     iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
       
   180     }
       
   181 
       
   182 // -----------------------------------------------------------------------------
       
   183 // Destructor
       
   184 // -----------------------------------------------------------------------------
       
   185 //
       
   186 EXPORT_C CMPXCollectionPlaylist::~CMPXCollectionPlaylist()
       
   187     {
       
   188     MPX_FUNC_EX("CMPXCollectionPlaylist::~CMPXCollectionPlaylist");
       
   189     delete iPath;
       
   190     iItemIndexes.Close();
       
   191     if (iColUtil)
       
   192         {
       
   193         iColUtil->Close();
       
   194         }
       
   195     delete iIncOpenUtil;
       
   196     }
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // Copy playlist content from other playlist except observers and session to 
       
   200 // collection server
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 EXPORT_C void CMPXCollectionPlaylist::CopyContentL(
       
   204     const CMPXCollectionPlaylist& aPlaylist)
       
   205     {
       
   206     MPX_FUNC_EX("CMPXCollectionPlaylist::CopyContentL(aPlaylist)");
       
   207     iRepeatMode=aPlaylist.iRepeatMode;
       
   208     iRepeatEnabled=aPlaylist.iRepeatEnabled;
       
   209     iShuffle=aPlaylist.iShuffle;
       
   210     iShuffleEnabled=aPlaylist.iShuffleEnabled;
       
   211     iRemote=aPlaylist.iRemote;
       
   212     delete iPath;
       
   213     iPath = NULL;
       
   214     iPath=CMPXCollectionPath::NewL(aPlaylist.Path());
       
   215     ::CopyArrayL(aPlaylist.iItemIndexes.Array(), iItemIndexes);
       
   216     iItemIndex=aPlaylist.iItemIndex;
       
   217     iEmbedded=aPlaylist.iEmbedded;
       
   218     iAutoPlaylist=aPlaylist.iAutoPlaylist;
       
   219     iAutoPlay=aPlaylist.iAutoPlay;
       
   220     iSingleItemPlaylist=aPlaylist.iSingleItemPlaylist;
       
   221     iPreInitPlugin=aPlaylist.iPreInitPlugin;
       
   222     
       
   223     if( !iColUtil )
       
   224         {
       
   225         iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);  
       
   226         }
       
   227     
       
   228     if (!iAutoPlaylist)
       
   229         {
       
   230         DoIncrementalOpenL();
       
   231         }
       
   232     }
       
   233 
       
   234 // -----------------------------------------------------------------------------
       
   235 // Advances path to next item
       
   236 // -----------------------------------------------------------------------------
       
   237 //
       
   238 EXPORT_C TBool CMPXCollectionPlaylist::Next( 
       
   239     TBool aIgnoreRepeat /*=EFalse*/ )
       
   240     {
       
   241     MPX_FUNC_EX("CMPXCollectionPlaylist::Next()");
       
   242     TInt nextPlIndex( KErrNotFound );
       
   243     TBool ret( NextIndex( aIgnoreRepeat, nextPlIndex ));
       
   244     if ( KErrNotFound != nextPlIndex )
       
   245         {
       
   246         iPath->Set( iItemIndexes[nextPlIndex] );
       
   247         if ( iShuffle && iItemIndex == Count()-1 )
       
   248             {
       
   249             MPX_TRAPD( err, SetShuffleL( iShuffle, ETrue ));
       
   250             if ( KErrNone != err )
       
   251                 {
       
   252                 ret = EFalse;
       
   253                 iItemIndex = 0;
       
   254                 iPath->Set( iItemIndexes[0] );
       
   255                 }
       
   256             }
       
   257         else
       
   258             {
       
   259             iItemIndex = nextPlIndex;
       
   260             }
       
   261         }
       
   262     return ret;
       
   263     }
       
   264 
       
   265 // -----------------------------------------------------------------------------
       
   266 // Gets the next index to play
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 EXPORT_C TBool CMPXCollectionPlaylist::NextIndex( 
       
   270     TBool aIgnoreRepeatOneMode,
       
   271     TInt& aPlaylistIndex ) const
       
   272     {
       
   273     MPX_FUNC("CMPXCollectionPlaylist::NextIndex()");
       
   274 
       
   275     TInt count( Count() );
       
   276     TBool ret( ETrue );
       
   277     if ( count <= 0 )
       
   278         {
       
   279         ret = EFalse;
       
   280         aPlaylistIndex = KErrNotFound;
       
   281         }
       
   282     else 
       
   283         {
       
   284         MPX_ASSERT( iItemIndex != -1 );
       
   285         aPlaylistIndex = iItemIndex;
       
   286 
       
   287         // If not in repeat one mode, then go to the next item,
       
   288         // otherwise leave index unchanged
       
   289         if (( ERepeatOne != iRepeatMode ) ||
       
   290             ( aIgnoreRepeatOneMode ))
       
   291             {
       
   292             // If not the last one in the list, find the next valid item
       
   293             if ( count-1 != aPlaylistIndex )
       
   294                 {
       
   295                 do
       
   296                     {
       
   297                     ++aPlaylistIndex;
       
   298                     }
       
   299                 while( aPlaylistIndex != count && 
       
   300                         iPath->IdOfIndex( iItemIndexes[aPlaylistIndex] )
       
   301                         == KMPXInvalidItemId );
       
   302                 }
       
   303 
       
   304             // If Last one in list, set to first
       
   305             if ( count-1 == iItemIndex || count == aPlaylistIndex )
       
   306                 {
       
   307                 if ( ERepeatOff == iRepeatMode )
       
   308                     {
       
   309                     ret = EFalse;
       
   310                     }
       
   311 
       
   312                 // If shuffle mode is on, choose a song to be the first song in the new
       
   313                 // randomized list.  This chooses the middle song, not exactly random,
       
   314                 // but this ensures that if this method is called multiple times
       
   315                 // it would return a consistent result.  The reason is because this
       
   316                 // method maybe called multiple times in a row by different clients, 
       
   317                 // so we want to make sure that each client returns the same result.
       
   318                 // If shuffle is off then choose the first item in list.
       
   319                 if ( iShuffle )
       
   320                     {
       
   321                     aPlaylistIndex = count / 2;
       
   322                     }
       
   323                 else
       
   324                     {
       
   325                     aPlaylistIndex = 0;
       
   326                     }
       
   327                 }
       
   328             }
       
   329         }
       
   330     MPX_DEBUG3("CMPXCollectionPlaylist::NextIndex %d %d", ret, aPlaylistIndex);
       
   331     return ret;
       
   332     }
       
   333 
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // Gets the path index of the item given it's position in the playlist.
       
   337 // -----------------------------------------------------------------------------
       
   338 //
       
   339 EXPORT_C TInt CMPXCollectionPlaylist::PathIndex( TInt aPlaylistIndex ) const
       
   340     {
       
   341     MPX_FUNC("CMPXCollectionPlaylist::PathIndex");
       
   342     MPX_ASSERT(aPlaylistIndex < Count());
       
   343     return iItemIndexes[aPlaylistIndex];
       
   344     }
       
   345 
       
   346 // -----------------------------------------------------------------------------
       
   347 // Advances path to previous item
       
   348 // -----------------------------------------------------------------------------
       
   349 //
       
   350 EXPORT_C TBool CMPXCollectionPlaylist::Previous( 
       
   351     TBool aIgnoreRepeat /*=EFalse*/ )
       
   352     {
       
   353     MPX_FUNC_EX("CMPXCollectionPlaylist::Previous");
       
   354     TBool ret=ETrue;
       
   355 
       
   356     TInt count( Count() );
       
   357     if ( count <= 0 )
       
   358         {
       
   359         ret = EFalse;
       
   360         }
       
   361     else if ( ERepeatOne != iRepeatMode ||
       
   362               aIgnoreRepeat )
       
   363         {
       
   364         // If first one in list, set to last
       
   365         if ( 0 == iItemIndex )
       
   366             {
       
   367             if (iShuffle)
       
   368                 { // re-shuffle
       
   369                 TRAP_IGNORE(SetShuffleL(iShuffle, EFalse));
       
   370                 }
       
   371             SetToLast();
       
   372             }
       
   373         else
       
   374             {
       
   375             // Find the next valid item
       
   376             //
       
   377             do
       
   378                 {
       
   379                 --iItemIndex;
       
   380                 if (iItemIndex>=0 && iItemIndex < iItemIndexes.Count())
       
   381                     {
       
   382                     iPath->Set(iItemIndexes[iItemIndex]);
       
   383                     }    
       
   384                 }
       
   385             while( iPath->Id() == KMPXInvalidItemId && 
       
   386                    iItemIndex != KErrNotFound );
       
   387                    
       
   388             if( iItemIndex < 0 )
       
   389                 {
       
   390                 iItemIndex=0;
       
   391                 ret=Previous();
       
   392                 }
       
   393             }
       
   394         }
       
   395     MPX_DEBUG2("CMPXCollectionPlaylist::PreviousL %i", iPath->Index());
       
   396     return ret;
       
   397     }
       
   398 
       
   399 // -----------------------------------------------------------------------------
       
   400 // Sets path to first item
       
   401 // -----------------------------------------------------------------------------
       
   402 //
       
   403 EXPORT_C void CMPXCollectionPlaylist::SetToFirst()
       
   404     {
       
   405     if (Count())
       
   406         {    
       
   407         iItemIndex=0;
       
   408         iPath->Set(iItemIndexes[iItemIndex]);
       
   409         }
       
   410     }
       
   411     
       
   412 // -----------------------------------------------------------------------------
       
   413 // Sets path to last item
       
   414 // -----------------------------------------------------------------------------
       
   415 //   
       
   416 EXPORT_C void CMPXCollectionPlaylist::SetToLast()
       
   417     {
       
   418     if (Count())
       
   419         {    
       
   420         iItemIndex=Count()-1;
       
   421         iPath->Set(iItemIndexes[iItemIndex]);
       
   422         }
       
   423     }
       
   424 
       
   425 // -----------------------------------------------------------------------------
       
   426 // Sets path to a particular index
       
   427 // -----------------------------------------------------------------------------
       
   428 //   
       
   429 EXPORT_C void CMPXCollectionPlaylist::SetToIndex( TInt aIndex )
       
   430     {
       
   431     MPX_ASSERT( aIndex >= -1 && aIndex < Count() );
       
   432     iItemIndex = aIndex;
       
   433     
       
   434     // Special case, the collection path does not support -1 no selection
       
   435     if( iItemIndex != -1 )
       
   436         {
       
   437         iPath->Set(iItemIndexes[iItemIndex]);
       
   438         }
       
   439     }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // Returns the number of items in the same container
       
   443 // -----------------------------------------------------------------------------
       
   444 //
       
   445 EXPORT_C TInt CMPXCollectionPlaylist::Count() const
       
   446     {
       
   447     return iItemIndexes.Count();
       
   448     }
       
   449 
       
   450 // -----------------------------------------------------------------------------
       
   451 // Returns the depth into the collection (0 = root level, 1 = first level etc.)
       
   452 // -----------------------------------------------------------------------------
       
   453 //    
       
   454 EXPORT_C TInt CMPXCollectionPlaylist::Levels() const
       
   455     {
       
   456     return iPath ? iPath->Levels() : 0; 
       
   457     }
       
   458 
       
   459 // -----------------------------------------------------------------------------
       
   460 // Returns play ordinal of current item in the playlist
       
   461 // -----------------------------------------------------------------------------
       
   462 //    
       
   463 EXPORT_C TInt CMPXCollectionPlaylist::Index() const
       
   464     {
       
   465     TInt index(KErrNotFound);
       
   466     if (Count() && iItemIndex < Count())
       
   467         {
       
   468         index = iItemIndex;
       
   469         }
       
   470     return index;
       
   471     }
       
   472 
       
   473 // -----------------------------------------------------------------------------
       
   474 // Is the collection stored on a remote device
       
   475 // -----------------------------------------------------------------------------
       
   476 //
       
   477 EXPORT_C TBool CMPXCollectionPlaylist::Remote() const
       
   478     {
       
   479     MPX_DEBUG2("-->CMPXCollectionPlaylist::Remote iColUtil 0x%08x", iColUtil);
       
   480     CMPXCollectionPlaylist *s = const_cast<CMPXCollectionPlaylist*>(this);
       
   481     if (!s->iColUtil && iPath)
       
   482         {
       
   483         TRAP_IGNORE(s->iColUtil=MMPXCollectionUtility::NewL(s, KMcModePlaylist));
       
   484         if (s->iColUtil)
       
   485             {
       
   486             s->iRemote=s->iColUtil->Collection().IsRemote(*iPath);
       
   487             }
       
   488         }
       
   489     MPX_DEBUG2("<--CMPXCollectionPlaylist::Remote iColUtil 0x%08x", iColUtil);
       
   490     return iRemote;
       
   491     }
       
   492 
       
   493 // -----------------------------------------------------------------------------
       
   494 // Repeat mode
       
   495 // -----------------------------------------------------------------------------
       
   496 //
       
   497 EXPORT_C CMPXCollectionPlaylist::TRepeatMode 
       
   498     CMPXCollectionPlaylist::RepeatMode() const
       
   499     {
       
   500     return iRepeatMode;
       
   501     }
       
   502 
       
   503 // -----------------------------------------------------------------------------
       
   504 // Shuffle
       
   505 // -----------------------------------------------------------------------------
       
   506 //    
       
   507 EXPORT_C TBool CMPXCollectionPlaylist::Shuffle() const
       
   508     {
       
   509     return iShuffle;
       
   510     }
       
   511 
       
   512 // -----------------------------------------------------------------------------
       
   513 // Collection path
       
   514 // -----------------------------------------------------------------------------
       
   515 //    
       
   516 EXPORT_C const CMPXCollectionPath& CMPXCollectionPlaylist::Path() const
       
   517     {
       
   518     return *iPath;
       
   519     }
       
   520     
       
   521 // -----------------------------------------------------------------------------
       
   522 // Get media properties for current item
       
   523 // -----------------------------------------------------------------------------
       
   524 //    
       
   525 EXPORT_C void CMPXCollectionPlaylist::MediaL(
       
   526     const TArray<TMPXAttribute>& aAttrs,
       
   527     MMPXCollectionMediaObserver& aMediaObs)
       
   528     {
       
   529     MPX_DEBUG4("-->CMPXCollectionPlaylist::MediaL 0x%08x, iColUtil 0x%08x, obs 0x%08x", 
       
   530                this, iColUtil, &aMediaObs);
       
   531     iMediaObs=&aMediaObs;
       
   532     if (!iColUtil)
       
   533         {
       
   534         iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);
       
   535         }
       
   536 
       
   537 #ifdef _DEBUG
       
   538     // For debug purposes, to test whether we can ever reach an invalid item
       
   539     if( iPath->Id() == KMPXInvalidItemId )
       
   540         {
       
   541         MPX_DEBUG1("CMPXCollectionPlaylist::MediaL Unloaded item");
       
   542         }
       
   543 #endif //_DEBUG
       
   544         
       
   545     iColUtil->Collection().MediaL(*iPath, aAttrs);
       
   546     MPX_DEBUG3("<--CMPXCollectionPlaylist::MediaL 0x%08x, iColUtil 0x%08x", 
       
   547                this, iColUtil);
       
   548     }
       
   549 
       
   550 // -----------------------------------------------------------------------------
       
   551 // Sets repeat mode
       
   552 // -----------------------------------------------------------------------------
       
   553 //
       
   554 EXPORT_C void CMPXCollectionPlaylist::SetRepeatMode(TRepeatMode aMode)
       
   555     {
       
   556     MPX_DEBUG2("CMPXCollectionPlaylist::SetRepeatMode(%d)", aMode);
       
   557     if ( iRepeatEnabled )
       
   558         {
       
   559         iRepeatMode=aMode;
       
   560         }
       
   561     else
       
   562         {
       
   563         iRepeatMode = ERepeatOff;
       
   564         }
       
   565     }
       
   566 
       
   567 // -----------------------------------------------------------------------------
       
   568 // Sets repeat enabled
       
   569 // -----------------------------------------------------------------------------
       
   570 //
       
   571 EXPORT_C void CMPXCollectionPlaylist::SetRepeatEnabled( TBool aEnable )
       
   572     {
       
   573     MPX_DEBUG2("CMPXCollectionPlaylist::SetRepeatEnabled(%d)", aEnable);
       
   574     iRepeatEnabled = aEnable;
       
   575     if ( !iRepeatEnabled )
       
   576         {
       
   577         SetRepeatMode( ERepeatOff );
       
   578         }
       
   579     }
       
   580 
       
   581 // -----------------------------------------------------------------------------
       
   582 // Sets shuffle
       
   583 // -----------------------------------------------------------------------------
       
   584 //    
       
   585 EXPORT_C void CMPXCollectionPlaylist::SetShuffleL(
       
   586     TBool aShuffle,
       
   587     TBool aCurrentToTop)
       
   588     {
       
   589     MPX_DEBUG3("CMPXCollectionPlaylist::SetShuffleL(%d, %d)", aShuffle, aCurrentToTop);
       
   590     
       
   591     if ( iShuffleEnabled )
       
   592         {
       
   593         iShuffle=aShuffle;
       
   594         }
       
   595     else
       
   596         {
       
   597         iShuffle = EFalse;
       
   598         }
       
   599     iItemIndexes.Reset();
       
   600     iItemIndex = KErrNotFound;
       
   601     TInt currentIndex(iPath->Index());
       
   602    
       
   603     if (iShuffle)
       
   604         {
       
   605         if ( iPath->Count() > 0 )
       
   606             {
       
   607             //
       
   608             // First, append item indexes in default order (i.e. 0,1,2...)
       
   609             // into a temp array
       
   610             //
       
   611             RArray<TInt> items;
       
   612             CleanupClosePushL(items);
       
   613             for (TInt i=0;i<iPath->Count();++i)
       
   614                 {
       
   615                 items.AppendL(i); 
       
   616                 }
       
   617             //
       
   618             // Get a seed for randomizing
       
   619             //
       
   620             TTime time;
       
   621             time.UniversalTime();
       
   622             TInt64 seed = time.Int64();  
       
   623 
       
   624             // Make sure current one is first in list.
       
   625             if (aCurrentToTop)
       
   626                 {
       
   627                 items.Remove(currentIndex);
       
   628                 iItemIndexes.AppendL(currentIndex);
       
   629                 }
       
   630 
       
   631             TInt count = items.Count();
       
   632             //
       
   633             // Pull the item indexes from the temp array, randomly,
       
   634             // removing pulled item so there are no repetitions
       
   635             //    
       
   636             for (TInt ii=0;ii<count;++ii)
       
   637                 {
       
   638                 TInt randIndex=Math::Rand(seed)%items.Count();
       
   639                 TInt index=items[randIndex];
       
   640                 items.Remove(randIndex);
       
   641                 iItemIndexes.AppendL(index);
       
   642                 }    
       
   643             CleanupStack::PopAndDestroy(&items);
       
   644             iItemIndex = 0;
       
   645             iPath->Set( iItemIndexes[iItemIndex] );
       
   646             }
       
   647         }
       
   648      else 
       
   649         {
       
   650         for (TInt i=0;i<iPath->Count();++i)
       
   651             {
       
   652             iItemIndexes.AppendL(i);// Append items in default order, i.e. 0,1,2...
       
   653             }
       
   654         // Set to current index
       
   655         iItemIndex = currentIndex;
       
   656         }
       
   657     }
       
   658 
       
   659 // -----------------------------------------------------------------------------
       
   660 // Sets shuffle enabled
       
   661 // -----------------------------------------------------------------------------
       
   662 //    
       
   663 EXPORT_C void CMPXCollectionPlaylist::SetShuffleEnabledL( TBool aEnable )
       
   664     {
       
   665     MPX_DEBUG2("CMPXCollectionPlaylist::SetShuffleEnabled(%d)", aEnable);
       
   666     if ( aEnable != iShuffleEnabled )
       
   667         {
       
   668         iShuffleEnabled = aEnable;
       
   669         SetShuffleL( EFalse, EFalse );
       
   670         }
       
   671     }
       
   672 
       
   673 // -----------------------------------------------------------------------------
       
   674 // Externalize object
       
   675 // -----------------------------------------------------------------------------
       
   676 //
       
   677 EXPORT_C void CMPXCollectionPlaylist::ExternalizeL(
       
   678     RWriteStream& aStream) const
       
   679     {
       
   680     aStream<<*iPath;
       
   681     aStream.WriteInt32L(iRepeatMode);
       
   682     aStream.WriteInt32L(iRemote);
       
   683     
       
   684     TInt n=iItemIndexes.Count();
       
   685     aStream.WriteInt32L(n);
       
   686     for (TInt ii=0;ii<n;++ii)
       
   687         {
       
   688         aStream.WriteInt32L(iItemIndexes[ii]);
       
   689         }           
       
   690     aStream.WriteInt32L(iShuffle);
       
   691     aStream.WriteInt32L(iItemIndex);
       
   692     aStream.WriteInt32L(iEmbedded);
       
   693     aStream.WriteInt32L(iRepeatEnabled);
       
   694     aStream.WriteInt32L(iShuffleEnabled);
       
   695     aStream.WriteInt32L(iAutoPlaylist);
       
   696     aStream.WriteInt32L(iAutoPlay);
       
   697     aStream.WriteInt32L(iSingleItemPlaylist);
       
   698     aStream.WriteInt32L(iPreInitPlugin);
       
   699     }
       
   700 
       
   701 // -----------------------------------------------------------------------------
       
   702 // Internalize object
       
   703 // -----------------------------------------------------------------------------
       
   704 //
       
   705 EXPORT_C void CMPXCollectionPlaylist::InternalizeL(RReadStream& aStream)
       
   706     {
       
   707     if (iPath)
       
   708         {
       
   709         delete iPath;
       
   710         iPath = NULL;
       
   711         }
       
   712     iPath=CMPXCollectionPath::NewL();
       
   713     aStream>>*iPath;
       
   714     iRepeatMode=static_cast<TRepeatMode>(aStream.ReadInt32L());
       
   715     iRemote=aStream.ReadInt32L();
       
   716     iItemIndexes.Reset();
       
   717     TInt n=aStream.ReadInt32L();
       
   718     for (TInt ii=0;ii<n;++ii)
       
   719         {
       
   720         iItemIndexes.AppendL(aStream.ReadInt32L());
       
   721         }     
       
   722     iShuffle=aStream.ReadInt32L();
       
   723     iItemIndex=aStream.ReadInt32L();
       
   724     iEmbedded=aStream.ReadInt32L();    
       
   725     iRepeatEnabled=aStream.ReadInt32L();
       
   726     iShuffleEnabled=aStream.ReadInt32L();
       
   727     iAutoPlaylist=aStream.ReadInt32L();
       
   728     iAutoPlay=aStream.ReadInt32L();
       
   729     iSingleItemPlaylist=aStream.ReadInt32L();
       
   730     iPreInitPlugin=aStream.ReadInt32L();
       
   731     if (iColUtil)
       
   732         {
       
   733         iColUtil->Close();
       
   734         iColUtil = NULL;
       
   735         }
       
   736     iColUtil=MMPXCollectionUtility::NewL(this);
       
   737     }
       
   738     
       
   739 // -----------------------------------------------------------------------------
       
   740 // Handle media from colllection
       
   741 // -----------------------------------------------------------------------------
       
   742 //
       
   743 void CMPXCollectionPlaylist::HandleCollectionMediaL(
       
   744     const CMPXMedia& aMedia, 
       
   745     TInt aError)
       
   746     {
       
   747     MPX_FUNC_EX("CMPXCollectionPlaylist::HandleCollectionMediaL");
       
   748     iMediaObs->HandleCollectionMediaL(aMedia, aError);
       
   749     }
       
   750 
       
   751 // -----------------------------------------------------------------------------
       
   752 // HandleCollectionMessage
       
   753 // -----------------------------------------------------------------------------
       
   754 //
       
   755 void CMPXCollectionPlaylist::HandleCollectionMessage(
       
   756     CMPXMessage* aMessage, 
       
   757     TInt aErr)
       
   758     {
       
   759     if (iPlObs)
       
   760         {
       
   761         TRAP_IGNORE(DoHandleCollectionMessageL(aMessage, aErr));
       
   762         } // pre-init playlist, don't bother to update itself, will be re-synced
       
   763     }
       
   764 
       
   765 // -----------------------------------------------------------------------------
       
   766 // Handle open event
       
   767 // -----------------------------------------------------------------------------
       
   768 //
       
   769 void CMPXCollectionPlaylist::HandleOpenL(
       
   770     const CMPXMedia& aEntries,
       
   771     TInt aIndex,
       
   772     TBool aComplete,
       
   773     TInt aError)
       
   774     {
       
   775     MPX_DEBUG4("-->CMPXCollectionPlaylist::HandleOpenL 0x%08x, iPlObs 0x%08x, iCollectonObs 0x%08x",
       
   776               this, iPlObs, iCollectionObs);
       
   777     if (KErrNone == aError)
       
   778         {
       
   779         if ( aEntries.IsSupported(KMPXMediaGeneralNonPermissibleActions ) )
       
   780             {
       
   781             // check for auto playlist, it is not writable and cacheable
       
   782             TMPXGeneralNonPermissibleActions attr(
       
   783                     aEntries.ValueTObjectL<TMPXGeneralNonPermissibleActions>( 
       
   784                     KMPXMediaGeneralNonPermissibleActions ) );
       
   785             if ( (attr & EMPXCache) && (attr & EMPXWrite))
       
   786                 {
       
   787                 iAutoPlaylist = ETrue;
       
   788                 }
       
   789             }                                        
       
   790         
       
   791         if (iPlObs)
       
   792             {
       
   793             DoHandleIncompleteOpenL(aEntries,aComplete);    
       
   794             }
       
   795         else if (iCollectionObs)
       
   796             { // callback right after swap, notify the playlist of the originator
       
   797             iCollectionObs->HandleOpenL(aEntries, aIndex, aComplete, aError);
       
   798             }
       
   799         }
       
   800     
       
   801     MPX_DEBUG4("<--CMPXCollectionPlaylist::HandleOpenL 0x%08x, iPlObs 0x%08x, iCollectonObs 0x%08x",
       
   802             this, iPlObs, iCollectionObs);
       
   803     }
       
   804 
       
   805 // -----------------------------------------------------------------------------
       
   806 // Handle open event
       
   807 // -----------------------------------------------------------------------------
       
   808 //
       
   809 void CMPXCollectionPlaylist::HandleOpenL(
       
   810     const CMPXCollectionPlaylist& aPlaylist,
       
   811     TInt aError)
       
   812     {
       
   813     (void)aPlaylist;
       
   814     (void)aError;
       
   815     }
       
   816 
       
   817 // -----------------------------------------------------------------------------
       
   818 // Set a new observer
       
   819 // -----------------------------------------------------------------------------
       
   820 //    
       
   821 EXPORT_C void CMPXCollectionPlaylist::SetObserver(
       
   822     MMPXCollectionMediaObserver& aMediaObs,
       
   823     MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/,
       
   824     MMPXCollectionObserver* aCollectionObs /*= NULL*/)
       
   825     {
       
   826     MPX_DEBUG4("-->CMPXCollectionPlaylist::SetObserver 0x%08x, mobs 0x%08x, plobs 0x%08x", 
       
   827                this, &aMediaObs, aPlObs);
       
   828     iMediaObs=&aMediaObs;
       
   829     iPlObs = aPlObs;
       
   830     iCollectionObs = aCollectionObs;
       
   831     MPX_DEBUG2("<--CMPXCollectionPlaylist::SetObserver 0x%08x", this);
       
   832     }
       
   833 
       
   834 // -----------------------------------------------------------------------------
       
   835 // Is this an embedded playlist
       
   836 // -----------------------------------------------------------------------------
       
   837 // 
       
   838 EXPORT_C TBool CMPXCollectionPlaylist::EmbeddedPlaylist() const
       
   839     {
       
   840     return iEmbedded;
       
   841     }
       
   842     
       
   843 // -----------------------------------------------------------------------------
       
   844 // Set a new observer
       
   845 // -----------------------------------------------------------------------------
       
   846 // 
       
   847 EXPORT_C void CMPXCollectionPlaylist::SetEmbeddedPlaylist( TBool aEmbedded )
       
   848     {
       
   849     iEmbedded = aEmbedded;
       
   850     }
       
   851 
       
   852 // ----------------------------------------------------------------------------
       
   853 // Set properities
       
   854 // ----------------------------------------------------------------------------
       
   855 //     
       
   856 EXPORT_C void CMPXCollectionPlaylist::SetL(const CMPXMedia& aMedia)
       
   857     {
       
   858     MPX_FUNC_EX("CMPXCollectionPlaylist::SetL()");
       
   859     if (!iColUtil)
       
   860         {
       
   861         iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);
       
   862         }
       
   863     
       
   864     CMPXCommand* cmd = CMPXCommand::NewL();
       
   865     CleanupStack::PushL( cmd );
       
   866     
       
   867     cmd->SetTObjectValueL( KMPXCommandGeneralId, KMPXCommandIdCollectionSet );
       
   868     cmd->SetTObjectValueL( KMPXCommandGeneralDoSync, EFalse );
       
   869     MPX_ASSERT( aMedia.IsSupported(KMPXMediaGeneralCollectionId) );
       
   870     TUid id( aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId) );
       
   871     cmd->SetTObjectValueL( KMPXCommandGeneralCollectionId, id.iUid );
       
   872     
       
   873     CMPXMedia* tmp = CMPXMedia::NewL(aMedia);
       
   874     CleanupStack::PushL( tmp );
       
   875     cmd->SetCObjectValueL<CMPXMedia>( KMPXCommandColSetMedia, tmp );
       
   876     CleanupStack::PopAndDestroy( tmp );   
       
   877      
       
   878     iColUtil->Collection().CommandL( *cmd );
       
   879     CleanupStack::PopAndDestroy( cmd );    
       
   880     }
       
   881 
       
   882 // ----------------------------------------------------------------------------
       
   883 // Remove outstanding requests
       
   884 // ----------------------------------------------------------------------------
       
   885 //     
       
   886 EXPORT_C void CMPXCollectionPlaylist::CancelRequest()
       
   887     {
       
   888     if (iColUtil)
       
   889         {
       
   890         iColUtil->Collection().CancelRequest();
       
   891         }
       
   892     }    
       
   893 
       
   894 // ----------------------------------------------------------------------------
       
   895 // Invalidate the playlist
       
   896 // ----------------------------------------------------------------------------
       
   897 //     
       
   898 EXPORT_C void CMPXCollectionPlaylist::Invalidate()
       
   899     {
       
   900     MPX_FUNC_EX("CMPXCollectionPlaylist::Invalidate");
       
   901     if( iPath )
       
   902         {
       
   903         iPath->Reset();
       
   904         }
       
   905     iItemIndexes.Reset();
       
   906     iItemIndex = KErrNotFound;
       
   907     iIncOpenUtil->Stop();
       
   908     }
       
   909 
       
   910 // ----------------------------------------------------------------------------
       
   911 // Restore Ordinal after path changed
       
   912 // ----------------------------------------------------------------------------
       
   913 //     
       
   914 void CMPXCollectionPlaylist::RestoreOrdinalL(
       
   915     const CMPXMedia& aEntries,
       
   916     TInt /*aIndex*/)
       
   917     {
       
   918     MPX_DEBUG3("-->CMPXCollectionPlaylist::RestoreOrdinalL 0x%08x, iPlObs 0x%08x", 
       
   919                this, iPlObs);
       
   920     MPX_DEBUG_PATH(*iPath);
       
   921     MPX_DEBUG2("CMPXCollectionPlaylist::RestoreOrdinal %i", iPath->Index());
       
   922 #ifdef _DEBUG
       
   923     MPX_DEBUG1("Original Play Order:");
       
   924     for (TInt ii = 0; ii < 15 && ii<Count(); ++ii)
       
   925         {
       
   926         MPX_DEBUG2("%d", iItemIndexes[ii]); 
       
   927         }
       
   928 #endif        
       
   929     // update path     
       
   930     TMPXItemId curId = iPath->Id();
       
   931     
       
   932     if ( !aEntries.IsSupported(KMPXMediaGeneralContainerPath) )
       
   933         {
       
   934         if ( iPlObs )
       
   935             {
       
   936             iPlObs->HandleCollectionPlaylistChange (KErrEof );
       
   937             }
       
   938         }
       
   939     else
       
   940         {
       
   941         CMPXCollectionPath
       
   942                 * path=aEntries.ValueCObjectL<CMPXCollectionPath> (KMPXMediaGeneralContainerPath );
       
   943         CleanupStack::PushL (path );
       
   944         // Check if path is for this playlist
       
   945         TInt levels = path->Levels ( );
       
   946         TBool valid(ETrue);
       
   947         if ( levels != iPath->Levels ( )-1 )
       
   948             {
       
   949             // Need to make sure the path was not clipped.
       
   950             // The number of levels between the old path  
       
   951             // and the new pathshould be the same.
       
   952             //
       
   953             valid = EFalse;
       
   954             }
       
   955 
       
   956         if ( valid )
       
   957             {
       
   958             TMPXItemId nextMostValidId=  KMPXInvalidItemId;
       
   959 
       
   960             if ( aEntries.IsSupported (KMPXMediaArrayContents ) )
       
   961                 {
       
   962                 RArray<TMPXItemId> ids;
       
   963                 CleanupClosePushL (ids );
       
   964                 const CMPXMediaArray * mediaArray=
       
   965                      aEntries.Value<CMPXMediaArray> (KMPXMediaArrayContents );
       
   966                 User::LeaveIfNull(const_cast<CMPXMediaArray*>(mediaArray));
       
   967                 TInt n=mediaArray->Count ( );
       
   968                 for (TInt k=0; k<n;++k )
       
   969                     {
       
   970                     TMPXItemId id = (mediaArray->AtL(k)->ValueTObjectL<TMPXItemId>(
       
   971                                                            KMPXMediaGeneralId));
       
   972 
       
   973                     ids.AppendL (id );
       
   974                     }
       
   975                 path->AppendL (ids.Array ( ) );
       
   976 
       
   977                 // Determine the next most valid item id
       
   978                 // by comparing previous item list vs current item list
       
   979                 // First search down the array list, then search up the array list
       
   980                 //
       
   981                 TInt c = iItemIndexes.Count ( );
       
   982                 for (TInt i=iItemIndex; i<c; ++i )
       
   983                     {
       
   984                     TMPXItemId prev = iPath->IdOfIndex ( i );
       
   985                     if ( ids.Find ( prev )!= KErrNotFound )
       
   986                         {
       
   987                         nextMostValidId = prev;
       
   988                         break;
       
   989                         }
       
   990                     }
       
   991                 if ( nextMostValidId == KMPXInvalidItemId && c )
       
   992                     {
       
   993                     for (TInt i=iItemIndex-1; i>0; --i )
       
   994                         {
       
   995                         TMPXItemId prev = iPath->IdOfIndex ( i );
       
   996                         if ( ids.Find ( prev )!= KErrNotFound )
       
   997                             {
       
   998                             nextMostValidId = prev;
       
   999                             break;
       
  1000                             }
       
  1001                         }
       
  1002                     }
       
  1003                 CleanupStack::PopAndDestroy (&ids );
       
  1004                 }
       
  1005             //if (aIndex>=0 && aIndex<path->Count())
       
  1006             if ( path->IndexOfId ( curId )!= KErrNotFound )
       
  1007                 {
       
  1008                 path->Set ( curId );
       
  1009                 }
       
  1010 
       
  1011             CleanupStack::Pop (path );
       
  1012             delete iPath;
       
  1013             iPath = path;
       
  1014 
       
  1015             if ( !iShuffle || !iShuffleEnabled )
       
  1016                 { // Just update the playlist content
       
  1017                 SetShuffleL (iShuffle, EFalse );
       
  1018                 }
       
  1019             else
       
  1020                 {// shuffle is on, try to restore previous play order
       
  1021                 RArray<TInt> items;
       
  1022                 CleanupClosePushL (items );
       
  1023                 TInt count = iItemIndexes.Count ( );
       
  1024                 TInt cPath = iPath->Count ( );
       
  1025                 TInt granularity = cPath ? cPath : 1; // magic number 1
       
  1026                 RArray<TInt> flags(granularity); // flags for the items in the playlist
       
  1027                 CleanupClosePushL (flags );
       
  1028                 for (TInt ii=0; ii<cPath; ++ii )
       
  1029                     { // Initialize the flags
       
  1030                     flags.AppendL (0 );
       
  1031                     }
       
  1032 
       
  1033                 // copy all of indices from orignial array up to number of items in the path
       
  1034                 for (TInt i=0; i<count; ++i )
       
  1035                     {
       
  1036                     TInt itemIndex = iItemIndexes[i];
       
  1037                     if ( itemIndex < cPath )
       
  1038                         {
       
  1039                         items.AppendL (itemIndex );
       
  1040                         flags[itemIndex] = 1; // set the flag
       
  1041                         } // Out of bound, not valid item anymore
       
  1042                     }
       
  1043 
       
  1044                 for (TInt j=0; j<cPath; ++j )
       
  1045                     {
       
  1046                     if ( !flags[j] )
       
  1047                         {
       
  1048                         items.AppendL (j );
       
  1049                         }
       
  1050                     }
       
  1051 
       
  1052                 CleanupStack::PopAndDestroy (&flags );
       
  1053                 ::CopyArrayL (items.Array ( ), iItemIndexes );
       
  1054                 CleanupStack::PopAndDestroy (&items );
       
  1055                 }
       
  1056             TInt err(KErrNone);
       
  1057 
       
  1058             TInt curIndex = iPath->IndexOfId (curId );
       
  1059             if ( iItemIndex >=Count ( ) )
       
  1060                 { // items removed
       
  1061                 SetToLast ( );
       
  1062                 if ( KErrNotFound == curIndex )
       
  1063                     { // current item removed at the end
       
  1064                     err = KErrEof;
       
  1065                     }
       
  1066                 }
       
  1067             else
       
  1068                 {
       
  1069                 if ( KErrNotFound != curIndex )
       
  1070                     {
       
  1071                     // Look up the shuffle index
       
  1072                     TInt itemIndex = iItemIndexes.Find (iPath->Index ( ) );
       
  1073                     if ( KErrNotFound != itemIndex )
       
  1074                         {
       
  1075                         iItemIndex = itemIndex;
       
  1076                         iPath->Set (iItemIndexes[iItemIndex] );
       
  1077                         }
       
  1078                     else
       
  1079                         { // this should never happen unless something wrong
       
  1080                         SetToLast ( );
       
  1081                         err = KErrNotFound;
       
  1082                         }
       
  1083                     }
       
  1084                 else
       
  1085                     { // current item removed, ensure the item was even valid
       
  1086                     err = KErrNotFound;
       
  1087 
       
  1088                     // If the current ID was invalid, then the previous iItemIndex is 
       
  1089                     // wrong as well. In this case, we use the next most valid ID
       
  1090                     // that is found by comparing the previous ID list to the current id list 
       
  1091                     // the next most valid ID has to exist in the new path
       
  1092                     //
       
  1093                     if ( nextMostValidId != KMPXInvalidItemId )
       
  1094                         {
       
  1095                         const TMPXItemId item = nextMostValidId; // compiler picks wrong set if no const
       
  1096                         iPath->Set (item );
       
  1097                         iItemIndex = iPath->Index ( );
       
  1098                         }
       
  1099                     else // back to first item
       
  1100                         {
       
  1101                         SetToFirst ( );
       
  1102                         }
       
  1103                     }
       
  1104                 }
       
  1105 
       
  1106             if ( iPlObs )
       
  1107                 {
       
  1108                 iPlObs->HandleCollectionPlaylistChange (err );
       
  1109                 }
       
  1110             }
       
  1111         else
       
  1112             {
       
  1113             CleanupStack::PopAndDestroy (path );
       
  1114             }
       
  1115 
       
  1116         MPX_DEBUG_PATH(*iPath);
       
  1117         MPX_DEBUG2("CMPXCollectionPlaylist::RestoreOrdinal %i", iPath->Index());
       
  1118 #ifdef _DEBUG
       
  1119         MPX_DEBUG1("New Play Order:");
       
  1120         for (TInt jj = 0; jj < 15 && jj<Count ( ); ++jj )
       
  1121             {
       
  1122             MPX_DEBUG2("%d", iItemIndexes[jj]);
       
  1123             }
       
  1124 #endif
       
  1125         }
       
  1126     MPX_DEBUG3("<--CMPXCollectionPlaylist::RestoreOrdinalL 0x%08x, iPlObs 0x%08x",
       
  1127             this, iPlObs);
       
  1128     }
       
  1129 
       
  1130 // -----------------------------------------------------------------------------
       
  1131 // DoHandleCollectionMessageL
       
  1132 // -----------------------------------------------------------------------------
       
  1133 //
       
  1134 void CMPXCollectionPlaylist::DoHandleCollectionMessageL(
       
  1135     CMPXMessage* aMessage, 
       
  1136     TInt aErr)
       
  1137     {
       
  1138     MPX_FUNC_EX("CMPXCollectionPlaylist::DoHandleCollectionMessageL");
       
  1139     TInt msgGeneralId(0);
       
  1140     if( aMessage )
       
  1141         {
       
  1142         msgGeneralId = aMessage->ValueTObjectL<TMPXMessageId>(KMPXMessageGeneralId);    
       
  1143         }
       
  1144     
       
  1145     if (KErrNone == aErr && KMPXMessageGeneral == msgGeneralId )
       
  1146         {
       
  1147         TInt event(aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralEvent));
       
  1148         TInt type(aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralType));
       
  1149         if (event == TMPXCollectionMessage::EError && 
       
  1150             type == EMcsMediaByPath)
       
  1151             {
       
  1152             MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL -- Error message for MediaL");
       
  1153             CMPXMedia* dummyMedia=CMPXMedia::NewL();
       
  1154             CleanupStack::PushL(dummyMedia);
       
  1155             iMediaObs->HandleCollectionMediaL(*dummyMedia, 
       
  1156                                 aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralData));
       
  1157             CleanupStack::PopAndDestroy(dummyMedia);
       
  1158             }
       
  1159         }
       
  1160     else if( aMessage && msgGeneralId == KMPXMessageIdItemChanged)
       
  1161         {
       
  1162         MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL -- KMPXMessageIdItemChanged");
       
  1163         // Multiple messages
       
  1164         //
       
  1165         TBool refresh(EFalse);
       
  1166         if( aMessage->IsSupported(KMPXMessageArrayContents) )
       
  1167             {
       
  1168             const CMPXMessageArray* messageArray =
       
  1169                     aMessage->Value<CMPXMessageArray>(KMPXMessageArrayContents);
       
  1170             User::LeaveIfNull(const_cast<CMPXMessageArray*>(messageArray));
       
  1171             TInt count(messageArray->Count());
       
  1172             for(TInt i=0; i<count; ++i )
       
  1173                 {
       
  1174                 refresh |= DoHandleCollectionChangeMessageL(*(messageArray->AtL(i)));
       
  1175                 }
       
  1176             }
       
  1177         // Single message
       
  1178         //
       
  1179         else
       
  1180             {
       
  1181             refresh = DoHandleCollectionChangeMessageL(*aMessage);
       
  1182             }
       
  1183         
       
  1184         // Re-open the playlist if necessary
       
  1185         //
       
  1186         if( refresh )
       
  1187             {
       
  1188             MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL - refresh due to KMPXMessageIdItemChanged");
       
  1189             if (iAutoPlaylist)
       
  1190                 {
       
  1191                 iPlObs->HandleCollectionPlaylistChange(iItemIndexes.Count() > 0 ? KErrNone : KErrEof);
       
  1192                 }
       
  1193             else
       
  1194                 {
       
  1195                 if( iPath->Levels() > 0 )
       
  1196                     {
       
  1197                     DoIncrementalOpenL();
       
  1198                     iReopenForChange = ETrue;
       
  1199                     }
       
  1200                 else
       
  1201                     {
       
  1202                     // Path has been clipped and not playable
       
  1203                     // 
       
  1204                     iPlObs->HandleCollectionPlaylistChange(KErrNotFound);
       
  1205                     }
       
  1206                 }
       
  1207             }
       
  1208         }
       
  1209     }
       
  1210 
       
  1211 // -----------------------------------------------------------------------------
       
  1212 // CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL
       
  1213 // -----------------------------------------------------------------------------
       
  1214 //
       
  1215 TBool CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL(
       
  1216     CMPXMessage& aMessage)
       
  1217     {
       
  1218     MPX_DEBUG3("-->CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL 0x%08x, iPlObs 0x%08x", 
       
  1219                this, iPlObs);
       
  1220     TBool refresh(EFalse);
       
  1221     TInt affectedIndex = KErrNotFound; // index of the id that is modified
       
  1222     
       
  1223     // Change event data
       
  1224     //
       
  1225     TUid collectionId( aMessage.ValueTObjectL<TUid>(KMPXMessageCollectionId) );
       
  1226     
       
  1227     TMPXChangeEventType changeType =
       
  1228         aMessage.ValueTObjectL<TMPXChangeEventType>(KMPXMessageChangeEventType);
       
  1229 
       
  1230     TMPXGeneralCategory category(EMPXNoCategory);
       
  1231     if( aMessage.IsSupported(KMPXMessageMediaGeneralCategory) )
       
  1232         {
       
  1233         category =
       
  1234             aMessage.ValueTObjectL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory);
       
  1235         }
       
  1236     
       
  1237     TMPXItemId itemId(0);
       
  1238     if( aMessage.IsSupported(KMPXMessageMediaGeneralId) )
       
  1239         {
       
  1240         itemId = aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaGeneralId);
       
  1241         }
       
  1242     
       
  1243     TMPXItemId deprecatedId(0);
       
  1244     if (aMessage.IsSupported(KMPXMessageMediaDeprecatedId))
       
  1245         {
       
  1246         deprecatedId = aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaDeprecatedId);
       
  1247         }
       
  1248     
       
  1249     // Check if the current item is being modified
       
  1250     //
       
  1251     TMPXItemId curItemId( iPath->Id() );
       
  1252     if( curItemId.ApproxEqual(itemId) )
       
  1253         {
       
  1254         affectedIndex = iPath->Index();
       
  1255         // Deleted
       
  1256         if( changeType == EMPXItemDeleted )
       
  1257             {
       
  1258             refresh = ETrue;
       
  1259             }
       
  1260         // Modified
       
  1261         else if( changeType == EMPXItemModified )
       
  1262             {
       
  1263             MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- modified");
       
  1264             refresh = ETrue;      
       
  1265             }
       
  1266         // else inserted should never happen
       
  1267         }
       
  1268     // Not the current item being modified, check collection path
       
  1269     // to see if the path needs to be refreshed
       
  1270     //
       
  1271     else
       
  1272         {
       
  1273         // Map Change Type
       
  1274         //
       
  1275         CMPXCollectionPath::TMPXCollectionPathChange 
       
  1276                             pChangeType(CMPXCollectionPath::EGroupModified);
       
  1277         if( category == EMPXPlaylist )
       
  1278             {
       
  1279             if( changeType == EMPXItemDeleted )
       
  1280                 {
       
  1281                 pChangeType = CMPXCollectionPath::EDeleted;    
       
  1282                 }
       
  1283             else
       
  1284                 {
       
  1285                 pChangeType = CMPXCollectionPath::EGroupModified;    
       
  1286                 }
       
  1287             }
       
  1288         else if( category == EMPXCollection )
       
  1289             {
       
  1290             if( changeType == EMPXItemModified )
       
  1291                 {
       
  1292                 pChangeType = CMPXCollectionPath::EGroupModified;
       
  1293                 }
       
  1294             }
       
  1295         else if( changeType == EMPXItemInserted )
       
  1296             {
       
  1297             pChangeType = CMPXCollectionPath::EAdded;    
       
  1298             }
       
  1299         else if( changeType == EMPXItemModified )
       
  1300             {
       
  1301             pChangeType = CMPXCollectionPath::EModified;    
       
  1302             }
       
  1303         else if( changeType == EMPXItemDeleted )
       
  1304             {
       
  1305             pChangeType = CMPXCollectionPath::EDeleted;
       
  1306             }
       
  1307         
       
  1308         // Check the collection path
       
  1309         //
       
  1310         if( iPath->Id(CMPXCollectionPath::ECollectionRoot) == collectionId.iUid )
       
  1311             {
       
  1312             TInt pUpdated = iPath->HandleChange( collectionId, itemId, 
       
  1313                                                deprecatedId, pChangeType, affectedIndex );
       
  1314             
       
  1315             if( pUpdated == CMPXCollectionPath::EPathClipped )
       
  1316                 {
       
  1317                 // Path clipped, playlist is no longer valid
       
  1318                 //
       
  1319                 MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- path clipped");
       
  1320                 Invalidate();
       
  1321                 if (iPlObs)
       
  1322                     {
       
  1323                     iPlObs->HandleCollectionPlaylistChange(KErrEof);
       
  1324                     }
       
  1325                 }
       
  1326             else if( pUpdated == CMPXCollectionPath::EPathModified )
       
  1327                 {
       
  1328                 // Path modified, something in needs to be refreshed
       
  1329                 //
       
  1330                 MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- path modified");
       
  1331                 refresh = ETrue;   
       
  1332                 }
       
  1333             }
       
  1334         }
       
  1335 
       
  1336     if (iAutoPlaylist && refresh)
       
  1337         {
       
  1338         // For autoplaylist, affected by the event.
       
  1339         // Path clip will never happen for autoplaylist
       
  1340         if (changeType == EMPXItemDeleted)
       
  1341             {
       
  1342             // item deleted in the autoplaylist, update the iPath to remove the item
       
  1343             // auso update iItemIndexes and iItemIndex
       
  1344             iPath->Remove(affectedIndex);
       
  1345             TInt itemIndex = KErrNotFound;
       
  1346             for (TInt i=0; i<iItemIndexes.Count(); i++)
       
  1347                 {
       
  1348                 if (iItemIndexes[i] == affectedIndex)
       
  1349                     {
       
  1350                     // remove the item
       
  1351                     iItemIndexes.Remove(i);
       
  1352                     itemIndex = i;
       
  1353                     }
       
  1354                 // because the item get removed, we still need to check the next item, if it's not the last
       
  1355                 if (i<iItemIndexes.Count() && iItemIndexes[i] > affectedIndex)
       
  1356                     {
       
  1357                     //index shift
       
  1358                     --iItemIndexes[i];
       
  1359                     }
       
  1360                 }
       
  1361             if (iItemIndexes.Count()>0)
       
  1362                 {
       
  1363                 // Still has items
       
  1364                 if (iItemIndex == itemIndex)
       
  1365                     {
       
  1366                     // current item get removed, iItemIndex already move to next
       
  1367                     if (iItemIndex >= iItemIndexes.Count()) 
       
  1368                         {
       
  1369                         iItemIndex = (iRepeatMode == ERepeatAll)? 0: iItemIndexes.Count()-1;
       
  1370                         }
       
  1371                     }
       
  1372                 else if (iItemIndex > itemIndex)
       
  1373                     {
       
  1374                     --iItemIndex;
       
  1375                     }
       
  1376                 iPath->Set(iItemIndexes[iItemIndex]);
       
  1377                 }
       
  1378             else
       
  1379                 {
       
  1380                 iItemIndex = KErrNotFound;
       
  1381                 }
       
  1382             }
       
  1383         }
       
  1384     
       
  1385     MPX_DEBUG4("<--CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL 0x%08x, iPlObs 0x%08x, refresh %d", 
       
  1386             this, iPlObs, refresh);
       
  1387     return refresh;
       
  1388     }
       
  1389 
       
  1390 // -----------------------------------------------------------------------------
       
  1391 // Start the incremental fetching 
       
  1392 // -----------------------------------------------------------------------------
       
  1393 //    
       
  1394 void CMPXCollectionPlaylist::DoIncrementalOpenL()
       
  1395     {
       
  1396     if(iSingleItemPlaylist)
       
  1397         {
       
  1398         return;
       
  1399         }
       
  1400     // Stop the utility first if we were fetching
       
  1401     //
       
  1402     iIncOpenUtil->Stop();
       
  1403     
       
  1404     // Copy of the path
       
  1405     //
       
  1406     CMPXCollectionPath* copy = iPath->ContainerPathL();
       
  1407     CleanupStack::PushL( copy );
       
  1408     
       
  1409     RArray<TMPXAttribute> attrs;
       
  1410     CleanupClosePushL( attrs );
       
  1411     TArray<TMPXAttribute> ary = attrs.Array();
       
  1412     
       
  1413     // Start the utility, 2 second delays so we don't flood the collection
       
  1414     // Have some delay as playlists are often destroyed! 
       
  1415     //
       
  1416     iIncOpenUtil->SetDelay( KIncrementalDelay ); 
       
  1417     iIncOpenUtil->StartL( *copy, ary, KIncrementalFetchSize, iPath->Index() , 
       
  1418                           CMPXCollectionOpenUtility::EFetchNormal );
       
  1419     CleanupStack::PopAndDestroy( &attrs );
       
  1420     CleanupStack::PopAndDestroy( copy );
       
  1421     }
       
  1422 
       
  1423 // -----------------------------------------------------------------------------
       
  1424 // Handle Incremental Open results
       
  1425 // -----------------------------------------------------------------------------
       
  1426 //  
       
  1427 void CMPXCollectionPlaylist::DoHandleIncompleteOpenL( const CMPXMedia& aMedia, TBool aComplete)
       
  1428     {
       
  1429     MPX_FUNC("<--CMPXCollectionPlaylist::DoHandleIncompleteOpenL");
       
  1430     if (iAutoPlaylist)
       
  1431         {
       
  1432         // Fill incomplete playlist, pending until inc open is used for playlist
       
  1433         /*
       
  1434         TInt index = iPath->IndexOfId(KMPXInvalidItemId)
       
  1435         if (!=KErrNotFound)
       
  1436             {
       
  1437             }
       
  1438         */
       
  1439         }
       
  1440     else
       
  1441         {
       
  1442         CMPXCollectionPath* newPath = iIncOpenUtil->PathL();
       
  1443         
       
  1444         // Re-select the previous item, if it failed then run
       
  1445         // the restore ordinal algorithm.
       
  1446         //
       
  1447         TInt index = newPath->IndexOfId(iPath->Id());
       
  1448         if( index != KErrNotFound && !iReopenForChange )
       
  1449             {
       
  1450             newPath->Set( index );
       
  1451             
       
  1452             delete iPath;
       
  1453             iPath = NULL;
       
  1454             iPath = newPath;
       
  1455             }
       
  1456         else 
       
  1457             {
       
  1458             delete newPath;
       
  1459             
       
  1460             TBool checkValid = (index == KErrNotFound) && (iReopenForChange);
       
  1461             if ( aComplete || (!checkValid))
       
  1462                 {                
       
  1463                 TBool checkForOpen = (index == KErrNotFound) && (!iReopenForChange);
       
  1464                 if ( !checkForOpen)
       
  1465                     {
       
  1466                     RestoreOrdinalL ( aMedia, 0);
       
  1467                     iReopenForChange = EFalse;
       
  1468                     }
       
  1469                 }
       
  1470             }      
       
  1471         }
       
  1472     }
       
  1473 // -----------------------------------------------------------------------------
       
  1474 // AutoPlay
       
  1475 // -----------------------------------------------------------------------------
       
  1476 //    
       
  1477 EXPORT_C TBool CMPXCollectionPlaylist::AutoPlay() const
       
  1478     {
       
  1479     return iAutoPlay;
       
  1480     }
       
  1481 
       
  1482 // -----------------------------------------------------------------------------
       
  1483 // Set AutoPlay
       
  1484 // -----------------------------------------------------------------------------
       
  1485 //    
       
  1486 EXPORT_C void CMPXCollectionPlaylist::SetAutoPlay(TBool aAutoPlay)
       
  1487     {
       
  1488     iAutoPlay = aAutoPlay;
       
  1489     }
       
  1490     
       
  1491     
       
  1492 // -----------------------------------------------------------------------------
       
  1493 // Set single item playlist
       
  1494 // -----------------------------------------------------------------------------
       
  1495 //
       
  1496 EXPORT_C void CMPXCollectionPlaylist::SetSingleItemPlaylist()
       
  1497     {
       
  1498     iSingleItemPlaylist = ETrue;
       
  1499     }
       
  1500     
       
  1501     
       
  1502 // -----------------------------------------------------------------------------
       
  1503 // Is single item playlist
       
  1504 // -----------------------------------------------------------------------------
       
  1505 //
       
  1506 EXPORT_C TBool CMPXCollectionPlaylist::IsSingleItemPlaylist()
       
  1507     {
       
  1508     return iSingleItemPlaylist;
       
  1509     }
       
  1510     
       
  1511 // -----------------------------------------------------------------------------
       
  1512 // PreInitPlugin
       
  1513 // -----------------------------------------------------------------------------
       
  1514 //    
       
  1515 EXPORT_C TBool CMPXCollectionPlaylist::PreInitPlugin() const
       
  1516     {
       
  1517     return iPreInitPlugin;
       
  1518     }
       
  1519 
       
  1520 // -----------------------------------------------------------------------------
       
  1521 // Set AutoPlay
       
  1522 // -----------------------------------------------------------------------------
       
  1523 //    
       
  1524 EXPORT_C void CMPXCollectionPlaylist::SetPreInitPlugin(TBool aPreInitPlugin)
       
  1525     {
       
  1526     iPreInitPlugin = aPreInitPlugin;
       
  1527     }
       
  1528     
       
  1529 
       
  1530 // End of file