--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/collectionframework/collectionutility/src/mpxcollectionplaylist.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,1530 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: implementation of collection playlist
+*
+*/
+
+#include <e32math.h>
+#include <mpxcollectionpath.h>
+#include <mpxcmn.h>
+#include <mpxcollectionutility.h>
+#include <mpxcollectionmessage.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmessagegeneraldefs.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediacontainerdefs.h>
+#include <mpxlog.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxcollectioncommanddefs.h>
+#include <mpxcollectionmessagedefs.h>
+#include <mpxmessagecontainerdefs.h>
+
+#include <mpxcollectionopenutility.h>
+
+#include "mpxcollectionplaylistobserver.h"
+#include "mpxcollectionplaylist.h"
+
+// CONSTANTS
+const TInt KIncrementalFetchSize = 400;
+const TInt KIncrementalDelay = 2000000;
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL()
+ {
+ MPX_DEBUG1("-->CMPXCollectionPlaylist::NewL()");
+ CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(NULL);
+ CleanupStack::PushL(p);
+ p->ConstructL();
+ CleanupStack::Pop(p);
+ MPX_DEBUG2("<--CMPXCollectionPlaylist::NewL() playlist 0x%08x", p);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
+ const CMPXCollectionPlaylist& aPlaylist,
+ MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
+ {
+ MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(pl, plobs) with plobs 0x%08x", aPlObs);
+ CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
+ CleanupStack::PushL(p);
+ p->ConstructL(aPlaylist);
+ CleanupStack::Pop(p);
+ MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
+ p, aPlObs);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
+ const CMPXCollectionPath& aPath,
+ MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
+ {
+ MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(path, plobs) with plobs 0x%08x", aPlObs);
+ CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
+ CleanupStack::PushL(p);
+ p->ConstructL(aPath);
+ CleanupStack::Pop(p);
+ MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
+ p, aPlObs);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist* CMPXCollectionPlaylist::NewL(
+ RReadStream& aStream,
+ MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/)
+ {
+ MPX_DEBUG2("-->CMPXCollectionPlaylist::NewL(strm, plobs) with plobs 0x%08x", aPlObs);
+ CMPXCollectionPlaylist* p = new(ELeave) CMPXCollectionPlaylist(aPlObs);
+ CleanupStack::PushL(p);
+ p->ConstructL(aStream);
+ CleanupStack::Pop(p);
+ MPX_DEBUG3("<--CMPXCollectionPlaylist::NewL(pl, plobs) playlist 0x%08x, , plobs 0x%08x",
+ p, aPlObs);
+ return p;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Default constructor
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPlaylist::CMPXCollectionPlaylist(
+ MMPXCollectionPlaylistObserver* aPlObs)
+: iRepeatMode(ERepeatOff), iShuffle(EFalse), iRemote(EFalse),
+ iItemIndex(KErrNotFound),iEmbedded(EFalse), iPlObs(aPlObs),
+ iRepeatEnabled(ETrue),
+ iShuffleEnabled(ETrue), iAutoPlaylist(EFalse),
+ iAutoPlay(ETrue), iSingleItemPlaylist(EFalse),
+ iPreInitPlugin(ETrue)
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::ConstructL(const CMPXCollectionPath& aPath)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aPath)");
+ iPath=CMPXCollectionPath::NewL(aPath);
+ iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
+ SetShuffleL(EFalse, EFalse);
+ if (!iAutoPlaylist)
+ {
+ DoIncrementalOpenL();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::ConstructL(
+ const CMPXCollectionPlaylist& aPlaylist)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aPlaylist)");
+ iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
+ CopyContentL(aPlaylist);
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::ConstructL(RReadStream& aStream)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL(aStream)");
+ InternalizeL(aStream);
+ iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
+ if (!iAutoPlaylist)
+ {
+ DoIncrementalOpenL();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::ConstructL()
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::ConstructL()");
+ iPath = CMPXCollectionPath::NewL();
+ iIncOpenUtil = CMPXCollectionOpenUtility::NewL( this, KMcModePlaylist );
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist::~CMPXCollectionPlaylist()
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::~CMPXCollectionPlaylist");
+ delete iPath;
+ iItemIndexes.Close();
+ if (iColUtil)
+ {
+ iColUtil->Close();
+ }
+ delete iIncOpenUtil;
+ }
+
+// -----------------------------------------------------------------------------
+// Copy playlist content from other playlist except observers and session to
+// collection server
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::CopyContentL(
+ const CMPXCollectionPlaylist& aPlaylist)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::CopyContentL(aPlaylist)");
+ iRepeatMode=aPlaylist.iRepeatMode;
+ iRepeatEnabled=aPlaylist.iRepeatEnabled;
+ iShuffle=aPlaylist.iShuffle;
+ iShuffleEnabled=aPlaylist.iShuffleEnabled;
+ iRemote=aPlaylist.iRemote;
+ delete iPath;
+ iPath = NULL;
+ iPath=CMPXCollectionPath::NewL(aPlaylist.Path());
+ ::CopyArrayL(aPlaylist.iItemIndexes.Array(), iItemIndexes);
+ iItemIndex=aPlaylist.iItemIndex;
+ iEmbedded=aPlaylist.iEmbedded;
+ iAutoPlaylist=aPlaylist.iAutoPlaylist;
+ iAutoPlay=aPlaylist.iAutoPlay;
+ iSingleItemPlaylist=aPlaylist.iSingleItemPlaylist;
+ iPreInitPlugin=aPlaylist.iPreInitPlugin;
+
+ if( !iColUtil )
+ {
+ iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);
+ }
+
+ if (!iAutoPlaylist)
+ {
+ DoIncrementalOpenL();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Advances path to next item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::Next(
+ TBool aIgnoreRepeat /*=EFalse*/ )
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::Next()");
+ TInt nextPlIndex( KErrNotFound );
+ TBool ret( NextIndex( aIgnoreRepeat, nextPlIndex ));
+ if ( KErrNotFound != nextPlIndex )
+ {
+ iPath->Set( iItemIndexes[nextPlIndex] );
+ if ( iShuffle && iItemIndex == Count()-1 )
+ {
+ MPX_TRAPD( err, SetShuffleL( iShuffle, ETrue ));
+ if ( KErrNone != err )
+ {
+ ret = EFalse;
+ iItemIndex = 0;
+ iPath->Set( iItemIndexes[0] );
+ }
+ }
+ else
+ {
+ iItemIndex = nextPlIndex;
+ }
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Gets the next index to play
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::NextIndex(
+ TBool aIgnoreRepeatOneMode,
+ TInt& aPlaylistIndex ) const
+ {
+ MPX_FUNC("CMPXCollectionPlaylist::NextIndex()");
+
+ TInt count( Count() );
+ TBool ret( ETrue );
+ if ( count <= 0 )
+ {
+ ret = EFalse;
+ aPlaylistIndex = KErrNotFound;
+ }
+ else
+ {
+ MPX_ASSERT( iItemIndex != -1 );
+ aPlaylistIndex = iItemIndex;
+
+ // If not in repeat one mode, then go to the next item,
+ // otherwise leave index unchanged
+ if (( ERepeatOne != iRepeatMode ) ||
+ ( aIgnoreRepeatOneMode ))
+ {
+ // If not the last one in the list, find the next valid item
+ if ( count-1 != aPlaylistIndex )
+ {
+ do
+ {
+ ++aPlaylistIndex;
+ }
+ while( aPlaylistIndex != count &&
+ iPath->IdOfIndex( iItemIndexes[aPlaylistIndex] )
+ == KMPXInvalidItemId );
+ }
+
+ // If Last one in list, set to first
+ if ( count-1 == iItemIndex || count == aPlaylistIndex )
+ {
+ if ( ERepeatOff == iRepeatMode )
+ {
+ ret = EFalse;
+ }
+
+ // If shuffle mode is on, choose a song to be the first song in the new
+ // randomized list. This chooses the middle song, not exactly random,
+ // but this ensures that if this method is called multiple times
+ // it would return a consistent result. The reason is because this
+ // method maybe called multiple times in a row by different clients,
+ // so we want to make sure that each client returns the same result.
+ // If shuffle is off then choose the first item in list.
+ if ( iShuffle )
+ {
+ aPlaylistIndex = count / 2;
+ }
+ else
+ {
+ aPlaylistIndex = 0;
+ }
+ }
+ }
+ }
+ MPX_DEBUG3("CMPXCollectionPlaylist::NextIndex %d %d", ret, aPlaylistIndex);
+ return ret;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Gets the path index of the item given it's position in the playlist.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPlaylist::PathIndex( TInt aPlaylistIndex ) const
+ {
+ MPX_FUNC("CMPXCollectionPlaylist::PathIndex");
+ MPX_ASSERT(aPlaylistIndex < Count());
+ return iItemIndexes[aPlaylistIndex];
+ }
+
+// -----------------------------------------------------------------------------
+// Advances path to previous item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::Previous(
+ TBool aIgnoreRepeat /*=EFalse*/ )
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::Previous");
+ TBool ret=ETrue;
+
+ TInt count( Count() );
+ if ( count <= 0 )
+ {
+ ret = EFalse;
+ }
+ else if ( ERepeatOne != iRepeatMode ||
+ aIgnoreRepeat )
+ {
+ // If first one in list, set to last
+ if ( 0 == iItemIndex )
+ {
+ if (iShuffle)
+ { // re-shuffle
+ TRAP_IGNORE(SetShuffleL(iShuffle, EFalse));
+ }
+ SetToLast();
+ }
+ else
+ {
+ // Find the next valid item
+ //
+ do
+ {
+ --iItemIndex;
+ if (iItemIndex>=0 && iItemIndex < iItemIndexes.Count())
+ {
+ iPath->Set(iItemIndexes[iItemIndex]);
+ }
+ }
+ while( iPath->Id() == KMPXInvalidItemId &&
+ iItemIndex != KErrNotFound );
+
+ if( iItemIndex < 0 )
+ {
+ iItemIndex=0;
+ ret=Previous();
+ }
+ }
+ }
+ MPX_DEBUG2("CMPXCollectionPlaylist::PreviousL %i", iPath->Index());
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Sets path to first item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetToFirst()
+ {
+ if (Count())
+ {
+ iItemIndex=0;
+ iPath->Set(iItemIndexes[iItemIndex]);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Sets path to last item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetToLast()
+ {
+ if (Count())
+ {
+ iItemIndex=Count()-1;
+ iPath->Set(iItemIndexes[iItemIndex]);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Sets path to a particular index
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetToIndex( TInt aIndex )
+ {
+ MPX_ASSERT( aIndex >= -1 && aIndex < Count() );
+ iItemIndex = aIndex;
+
+ // Special case, the collection path does not support -1 no selection
+ if( iItemIndex != -1 )
+ {
+ iPath->Set(iItemIndexes[iItemIndex]);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the number of items in the same container
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPlaylist::Count() const
+ {
+ return iItemIndexes.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the depth into the collection (0 = root level, 1 = first level etc.)
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPlaylist::Levels() const
+ {
+ return iPath ? iPath->Levels() : 0;
+ }
+
+// -----------------------------------------------------------------------------
+// Returns play ordinal of current item in the playlist
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPlaylist::Index() const
+ {
+ TInt index(KErrNotFound);
+ if (Count() && iItemIndex < Count())
+ {
+ index = iItemIndex;
+ }
+ return index;
+ }
+
+// -----------------------------------------------------------------------------
+// Is the collection stored on a remote device
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::Remote() const
+ {
+ MPX_DEBUG2("-->CMPXCollectionPlaylist::Remote iColUtil 0x%08x", iColUtil);
+ CMPXCollectionPlaylist *s = const_cast<CMPXCollectionPlaylist*>(this);
+ if (!s->iColUtil && iPath)
+ {
+ TRAP_IGNORE(s->iColUtil=MMPXCollectionUtility::NewL(s, KMcModePlaylist));
+ if (s->iColUtil)
+ {
+ s->iRemote=s->iColUtil->Collection().IsRemote(*iPath);
+ }
+ }
+ MPX_DEBUG2("<--CMPXCollectionPlaylist::Remote iColUtil 0x%08x", iColUtil);
+ return iRemote;
+ }
+
+// -----------------------------------------------------------------------------
+// Repeat mode
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPlaylist::TRepeatMode
+ CMPXCollectionPlaylist::RepeatMode() const
+ {
+ return iRepeatMode;
+ }
+
+// -----------------------------------------------------------------------------
+// Shuffle
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::Shuffle() const
+ {
+ return iShuffle;
+ }
+
+// -----------------------------------------------------------------------------
+// Collection path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const CMPXCollectionPath& CMPXCollectionPlaylist::Path() const
+ {
+ return *iPath;
+ }
+
+// -----------------------------------------------------------------------------
+// Get media properties for current item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::MediaL(
+ const TArray<TMPXAttribute>& aAttrs,
+ MMPXCollectionMediaObserver& aMediaObs)
+ {
+ MPX_DEBUG4("-->CMPXCollectionPlaylist::MediaL 0x%08x, iColUtil 0x%08x, obs 0x%08x",
+ this, iColUtil, &aMediaObs);
+ iMediaObs=&aMediaObs;
+ if (!iColUtil)
+ {
+ iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);
+ }
+
+#ifdef _DEBUG
+ // For debug purposes, to test whether we can ever reach an invalid item
+ if( iPath->Id() == KMPXInvalidItemId )
+ {
+ MPX_DEBUG1("CMPXCollectionPlaylist::MediaL Unloaded item");
+ }
+#endif //_DEBUG
+
+ iColUtil->Collection().MediaL(*iPath, aAttrs);
+ MPX_DEBUG3("<--CMPXCollectionPlaylist::MediaL 0x%08x, iColUtil 0x%08x",
+ this, iColUtil);
+ }
+
+// -----------------------------------------------------------------------------
+// Sets repeat mode
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetRepeatMode(TRepeatMode aMode)
+ {
+ MPX_DEBUG2("CMPXCollectionPlaylist::SetRepeatMode(%d)", aMode);
+ if ( iRepeatEnabled )
+ {
+ iRepeatMode=aMode;
+ }
+ else
+ {
+ iRepeatMode = ERepeatOff;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Sets repeat enabled
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetRepeatEnabled( TBool aEnable )
+ {
+ MPX_DEBUG2("CMPXCollectionPlaylist::SetRepeatEnabled(%d)", aEnable);
+ iRepeatEnabled = aEnable;
+ if ( !iRepeatEnabled )
+ {
+ SetRepeatMode( ERepeatOff );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Sets shuffle
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetShuffleL(
+ TBool aShuffle,
+ TBool aCurrentToTop)
+ {
+ MPX_DEBUG3("CMPXCollectionPlaylist::SetShuffleL(%d, %d)", aShuffle, aCurrentToTop);
+
+ if ( iShuffleEnabled )
+ {
+ iShuffle=aShuffle;
+ }
+ else
+ {
+ iShuffle = EFalse;
+ }
+ iItemIndexes.Reset();
+ iItemIndex = KErrNotFound;
+ TInt currentIndex(iPath->Index());
+
+ if (iShuffle)
+ {
+ if ( iPath->Count() > 0 )
+ {
+ //
+ // First, append item indexes in default order (i.e. 0,1,2...)
+ // into a temp array
+ //
+ RArray<TInt> items;
+ CleanupClosePushL(items);
+ for (TInt i=0;i<iPath->Count();++i)
+ {
+ items.AppendL(i);
+ }
+ //
+ // Get a seed for randomizing
+ //
+ TTime time;
+ time.UniversalTime();
+ TInt64 seed = time.Int64();
+
+ // Make sure current one is first in list.
+ if (aCurrentToTop)
+ {
+ items.Remove(currentIndex);
+ iItemIndexes.AppendL(currentIndex);
+ }
+
+ TInt count = items.Count();
+ //
+ // Pull the item indexes from the temp array, randomly,
+ // removing pulled item so there are no repetitions
+ //
+ for (TInt ii=0;ii<count;++ii)
+ {
+ TInt randIndex=Math::Rand(seed)%items.Count();
+ TInt index=items[randIndex];
+ items.Remove(randIndex);
+ iItemIndexes.AppendL(index);
+ }
+ CleanupStack::PopAndDestroy(&items);
+ iItemIndex = 0;
+ iPath->Set( iItemIndexes[iItemIndex] );
+ }
+ }
+ else
+ {
+ for (TInt i=0;i<iPath->Count();++i)
+ {
+ iItemIndexes.AppendL(i);// Append items in default order, i.e. 0,1,2...
+ }
+ // Set to current index
+ iItemIndex = currentIndex;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Sets shuffle enabled
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetShuffleEnabledL( TBool aEnable )
+ {
+ MPX_DEBUG2("CMPXCollectionPlaylist::SetShuffleEnabled(%d)", aEnable);
+ if ( aEnable != iShuffleEnabled )
+ {
+ iShuffleEnabled = aEnable;
+ SetShuffleL( EFalse, EFalse );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Externalize object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::ExternalizeL(
+ RWriteStream& aStream) const
+ {
+ aStream<<*iPath;
+ aStream.WriteInt32L(iRepeatMode);
+ aStream.WriteInt32L(iRemote);
+
+ TInt n=iItemIndexes.Count();
+ aStream.WriteInt32L(n);
+ for (TInt ii=0;ii<n;++ii)
+ {
+ aStream.WriteInt32L(iItemIndexes[ii]);
+ }
+ aStream.WriteInt32L(iShuffle);
+ aStream.WriteInt32L(iItemIndex);
+ aStream.WriteInt32L(iEmbedded);
+ aStream.WriteInt32L(iRepeatEnabled);
+ aStream.WriteInt32L(iShuffleEnabled);
+ aStream.WriteInt32L(iAutoPlaylist);
+ aStream.WriteInt32L(iAutoPlay);
+ aStream.WriteInt32L(iSingleItemPlaylist);
+ aStream.WriteInt32L(iPreInitPlugin);
+ }
+
+// -----------------------------------------------------------------------------
+// Internalize object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::InternalizeL(RReadStream& aStream)
+ {
+ if (iPath)
+ {
+ delete iPath;
+ iPath = NULL;
+ }
+ iPath=CMPXCollectionPath::NewL();
+ aStream>>*iPath;
+ iRepeatMode=static_cast<TRepeatMode>(aStream.ReadInt32L());
+ iRemote=aStream.ReadInt32L();
+ iItemIndexes.Reset();
+ TInt n=aStream.ReadInt32L();
+ for (TInt ii=0;ii<n;++ii)
+ {
+ iItemIndexes.AppendL(aStream.ReadInt32L());
+ }
+ iShuffle=aStream.ReadInt32L();
+ iItemIndex=aStream.ReadInt32L();
+ iEmbedded=aStream.ReadInt32L();
+ iRepeatEnabled=aStream.ReadInt32L();
+ iShuffleEnabled=aStream.ReadInt32L();
+ iAutoPlaylist=aStream.ReadInt32L();
+ iAutoPlay=aStream.ReadInt32L();
+ iSingleItemPlaylist=aStream.ReadInt32L();
+ iPreInitPlugin=aStream.ReadInt32L();
+ if (iColUtil)
+ {
+ iColUtil->Close();
+ iColUtil = NULL;
+ }
+ iColUtil=MMPXCollectionUtility::NewL(this);
+ }
+
+// -----------------------------------------------------------------------------
+// Handle media from colllection
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::HandleCollectionMediaL(
+ const CMPXMedia& aMedia,
+ TInt aError)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::HandleCollectionMediaL");
+ iMediaObs->HandleCollectionMediaL(aMedia, aError);
+ }
+
+// -----------------------------------------------------------------------------
+// HandleCollectionMessage
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::HandleCollectionMessage(
+ CMPXMessage* aMessage,
+ TInt aErr)
+ {
+ if (iPlObs)
+ {
+ TRAP_IGNORE(DoHandleCollectionMessageL(aMessage, aErr));
+ } // pre-init playlist, don't bother to update itself, will be re-synced
+ }
+
+// -----------------------------------------------------------------------------
+// Handle open event
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::HandleOpenL(
+ const CMPXMedia& aEntries,
+ TInt aIndex,
+ TBool aComplete,
+ TInt aError)
+ {
+ MPX_DEBUG4("-->CMPXCollectionPlaylist::HandleOpenL 0x%08x, iPlObs 0x%08x, iCollectonObs 0x%08x",
+ this, iPlObs, iCollectionObs);
+ if (KErrNone == aError)
+ {
+ if ( aEntries.IsSupported(KMPXMediaGeneralNonPermissibleActions ) )
+ {
+ // check for auto playlist, it is not writable and cacheable
+ TMPXGeneralNonPermissibleActions attr(
+ aEntries.ValueTObjectL<TMPXGeneralNonPermissibleActions>(
+ KMPXMediaGeneralNonPermissibleActions ) );
+ if ( (attr & EMPXCache) && (attr & EMPXWrite))
+ {
+ iAutoPlaylist = ETrue;
+ }
+ }
+
+ if (iPlObs)
+ {
+ DoHandleIncompleteOpenL(aEntries,aComplete);
+ }
+ else if (iCollectionObs)
+ { // callback right after swap, notify the playlist of the originator
+ iCollectionObs->HandleOpenL(aEntries, aIndex, aComplete, aError);
+ }
+ }
+
+ MPX_DEBUG4("<--CMPXCollectionPlaylist::HandleOpenL 0x%08x, iPlObs 0x%08x, iCollectonObs 0x%08x",
+ this, iPlObs, iCollectionObs);
+ }
+
+// -----------------------------------------------------------------------------
+// Handle open event
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::HandleOpenL(
+ const CMPXCollectionPlaylist& aPlaylist,
+ TInt aError)
+ {
+ (void)aPlaylist;
+ (void)aError;
+ }
+
+// -----------------------------------------------------------------------------
+// Set a new observer
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetObserver(
+ MMPXCollectionMediaObserver& aMediaObs,
+ MMPXCollectionPlaylistObserver* aPlObs /*= NULL*/,
+ MMPXCollectionObserver* aCollectionObs /*= NULL*/)
+ {
+ MPX_DEBUG4("-->CMPXCollectionPlaylist::SetObserver 0x%08x, mobs 0x%08x, plobs 0x%08x",
+ this, &aMediaObs, aPlObs);
+ iMediaObs=&aMediaObs;
+ iPlObs = aPlObs;
+ iCollectionObs = aCollectionObs;
+ MPX_DEBUG2("<--CMPXCollectionPlaylist::SetObserver 0x%08x", this);
+ }
+
+// -----------------------------------------------------------------------------
+// Is this an embedded playlist
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::EmbeddedPlaylist() const
+ {
+ return iEmbedded;
+ }
+
+// -----------------------------------------------------------------------------
+// Set a new observer
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetEmbeddedPlaylist( TBool aEmbedded )
+ {
+ iEmbedded = aEmbedded;
+ }
+
+// ----------------------------------------------------------------------------
+// Set properities
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetL(const CMPXMedia& aMedia)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::SetL()");
+ if (!iColUtil)
+ {
+ iColUtil=MMPXCollectionUtility::NewL(this ,KMcModePlaylist);
+ }
+
+ CMPXCommand* cmd = CMPXCommand::NewL();
+ CleanupStack::PushL( cmd );
+
+ cmd->SetTObjectValueL( KMPXCommandGeneralId, KMPXCommandIdCollectionSet );
+ cmd->SetTObjectValueL( KMPXCommandGeneralDoSync, EFalse );
+ MPX_ASSERT( aMedia.IsSupported(KMPXMediaGeneralCollectionId) );
+ TUid id( aMedia.ValueTObjectL<TUid>(KMPXMediaGeneralCollectionId) );
+ cmd->SetTObjectValueL( KMPXCommandGeneralCollectionId, id.iUid );
+
+ CMPXMedia* tmp = CMPXMedia::NewL(aMedia);
+ CleanupStack::PushL( tmp );
+ cmd->SetCObjectValueL<CMPXMedia>( KMPXCommandColSetMedia, tmp );
+ CleanupStack::PopAndDestroy( tmp );
+
+ iColUtil->Collection().CommandL( *cmd );
+ CleanupStack::PopAndDestroy( cmd );
+ }
+
+// ----------------------------------------------------------------------------
+// Remove outstanding requests
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::CancelRequest()
+ {
+ if (iColUtil)
+ {
+ iColUtil->Collection().CancelRequest();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// Invalidate the playlist
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::Invalidate()
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::Invalidate");
+ if( iPath )
+ {
+ iPath->Reset();
+ }
+ iItemIndexes.Reset();
+ iItemIndex = KErrNotFound;
+ iIncOpenUtil->Stop();
+ }
+
+// ----------------------------------------------------------------------------
+// Restore Ordinal after path changed
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::RestoreOrdinalL(
+ const CMPXMedia& aEntries,
+ TInt /*aIndex*/)
+ {
+ MPX_DEBUG3("-->CMPXCollectionPlaylist::RestoreOrdinalL 0x%08x, iPlObs 0x%08x",
+ this, iPlObs);
+ MPX_DEBUG_PATH(*iPath);
+ MPX_DEBUG2("CMPXCollectionPlaylist::RestoreOrdinal %i", iPath->Index());
+#ifdef _DEBUG
+ MPX_DEBUG1("Original Play Order:");
+ for (TInt ii = 0; ii < 15 && ii<Count(); ++ii)
+ {
+ MPX_DEBUG2("%d", iItemIndexes[ii]);
+ }
+#endif
+ // update path
+ TMPXItemId curId = iPath->Id();
+
+ if ( !aEntries.IsSupported(KMPXMediaGeneralContainerPath) )
+ {
+ if ( iPlObs )
+ {
+ iPlObs->HandleCollectionPlaylistChange (KErrEof );
+ }
+ }
+ else
+ {
+ CMPXCollectionPath
+ * path=aEntries.ValueCObjectL<CMPXCollectionPath> (KMPXMediaGeneralContainerPath );
+ CleanupStack::PushL (path );
+ // Check if path is for this playlist
+ TInt levels = path->Levels ( );
+ TBool valid(ETrue);
+ if ( levels != iPath->Levels ( )-1 )
+ {
+ // Need to make sure the path was not clipped.
+ // The number of levels between the old path
+ // and the new pathshould be the same.
+ //
+ valid = EFalse;
+ }
+
+ if ( valid )
+ {
+ TMPXItemId nextMostValidId= KMPXInvalidItemId;
+
+ if ( aEntries.IsSupported (KMPXMediaArrayContents ) )
+ {
+ RArray<TMPXItemId> ids;
+ CleanupClosePushL (ids );
+ const CMPXMediaArray * mediaArray=
+ aEntries.Value<CMPXMediaArray> (KMPXMediaArrayContents );
+ User::LeaveIfNull(const_cast<CMPXMediaArray*>(mediaArray));
+ TInt n=mediaArray->Count ( );
+ for (TInt k=0; k<n;++k )
+ {
+ TMPXItemId id = (mediaArray->AtL(k)->ValueTObjectL<TMPXItemId>(
+ KMPXMediaGeneralId));
+
+ ids.AppendL (id );
+ }
+ path->AppendL (ids.Array ( ) );
+
+ // Determine the next most valid item id
+ // by comparing previous item list vs current item list
+ // First search down the array list, then search up the array list
+ //
+ TInt c = iItemIndexes.Count ( );
+ for (TInt i=iItemIndex; i<c; ++i )
+ {
+ TMPXItemId prev = iPath->IdOfIndex ( i );
+ if ( ids.Find ( prev )!= KErrNotFound )
+ {
+ nextMostValidId = prev;
+ break;
+ }
+ }
+ if ( nextMostValidId == KMPXInvalidItemId && c )
+ {
+ for (TInt i=iItemIndex-1; i>0; --i )
+ {
+ TMPXItemId prev = iPath->IdOfIndex ( i );
+ if ( ids.Find ( prev )!= KErrNotFound )
+ {
+ nextMostValidId = prev;
+ break;
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy (&ids );
+ }
+ //if (aIndex>=0 && aIndex<path->Count())
+ if ( path->IndexOfId ( curId )!= KErrNotFound )
+ {
+ path->Set ( curId );
+ }
+
+ CleanupStack::Pop (path );
+ delete iPath;
+ iPath = path;
+
+ if ( !iShuffle || !iShuffleEnabled )
+ { // Just update the playlist content
+ SetShuffleL (iShuffle, EFalse );
+ }
+ else
+ {// shuffle is on, try to restore previous play order
+ RArray<TInt> items;
+ CleanupClosePushL (items );
+ TInt count = iItemIndexes.Count ( );
+ TInt cPath = iPath->Count ( );
+ TInt granularity = cPath ? cPath : 1; // magic number 1
+ RArray<TInt> flags(granularity); // flags for the items in the playlist
+ CleanupClosePushL (flags );
+ for (TInt ii=0; ii<cPath; ++ii )
+ { // Initialize the flags
+ flags.AppendL (0 );
+ }
+
+ // copy all of indices from orignial array up to number of items in the path
+ for (TInt i=0; i<count; ++i )
+ {
+ TInt itemIndex = iItemIndexes[i];
+ if ( itemIndex < cPath )
+ {
+ items.AppendL (itemIndex );
+ flags[itemIndex] = 1; // set the flag
+ } // Out of bound, not valid item anymore
+ }
+
+ for (TInt j=0; j<cPath; ++j )
+ {
+ if ( !flags[j] )
+ {
+ items.AppendL (j );
+ }
+ }
+
+ CleanupStack::PopAndDestroy (&flags );
+ ::CopyArrayL (items.Array ( ), iItemIndexes );
+ CleanupStack::PopAndDestroy (&items );
+ }
+ TInt err(KErrNone);
+
+ TInt curIndex = iPath->IndexOfId (curId );
+ if ( iItemIndex >=Count ( ) )
+ { // items removed
+ SetToLast ( );
+ if ( KErrNotFound == curIndex )
+ { // current item removed at the end
+ err = KErrEof;
+ }
+ }
+ else
+ {
+ if ( KErrNotFound != curIndex )
+ {
+ // Look up the shuffle index
+ TInt itemIndex = iItemIndexes.Find (iPath->Index ( ) );
+ if ( KErrNotFound != itemIndex )
+ {
+ iItemIndex = itemIndex;
+ iPath->Set (iItemIndexes[iItemIndex] );
+ }
+ else
+ { // this should never happen unless something wrong
+ SetToLast ( );
+ err = KErrNotFound;
+ }
+ }
+ else
+ { // current item removed, ensure the item was even valid
+ err = KErrNotFound;
+
+ // If the current ID was invalid, then the previous iItemIndex is
+ // wrong as well. In this case, we use the next most valid ID
+ // that is found by comparing the previous ID list to the current id list
+ // the next most valid ID has to exist in the new path
+ //
+ if ( nextMostValidId != KMPXInvalidItemId )
+ {
+ const TMPXItemId item = nextMostValidId; // compiler picks wrong set if no const
+ iPath->Set (item );
+ iItemIndex = iPath->Index ( );
+ }
+ else // back to first item
+ {
+ SetToFirst ( );
+ }
+ }
+ }
+
+ if ( iPlObs )
+ {
+ iPlObs->HandleCollectionPlaylistChange (err );
+ }
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy (path );
+ }
+
+ MPX_DEBUG_PATH(*iPath);
+ MPX_DEBUG2("CMPXCollectionPlaylist::RestoreOrdinal %i", iPath->Index());
+#ifdef _DEBUG
+ MPX_DEBUG1("New Play Order:");
+ for (TInt jj = 0; jj < 15 && jj<Count ( ); ++jj )
+ {
+ MPX_DEBUG2("%d", iItemIndexes[jj]);
+ }
+#endif
+ }
+ MPX_DEBUG3("<--CMPXCollectionPlaylist::RestoreOrdinalL 0x%08x, iPlObs 0x%08x",
+ this, iPlObs);
+ }
+
+// -----------------------------------------------------------------------------
+// DoHandleCollectionMessageL
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::DoHandleCollectionMessageL(
+ CMPXMessage* aMessage,
+ TInt aErr)
+ {
+ MPX_FUNC_EX("CMPXCollectionPlaylist::DoHandleCollectionMessageL");
+ TInt msgGeneralId(0);
+ if( aMessage )
+ {
+ msgGeneralId = aMessage->ValueTObjectL<TMPXMessageId>(KMPXMessageGeneralId);
+ }
+
+ if (KErrNone == aErr && KMPXMessageGeneral == msgGeneralId )
+ {
+ TInt event(aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralEvent));
+ TInt type(aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralType));
+ if (event == TMPXCollectionMessage::EError &&
+ type == EMcsMediaByPath)
+ {
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL -- Error message for MediaL");
+ CMPXMedia* dummyMedia=CMPXMedia::NewL();
+ CleanupStack::PushL(dummyMedia);
+ iMediaObs->HandleCollectionMediaL(*dummyMedia,
+ aMessage->ValueTObjectL<TInt>(KMPXMessageGeneralData));
+ CleanupStack::PopAndDestroy(dummyMedia);
+ }
+ }
+ else if( aMessage && msgGeneralId == KMPXMessageIdItemChanged)
+ {
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL -- KMPXMessageIdItemChanged");
+ // Multiple messages
+ //
+ TBool refresh(EFalse);
+ if( aMessage->IsSupported(KMPXMessageArrayContents) )
+ {
+ const CMPXMessageArray* messageArray =
+ aMessage->Value<CMPXMessageArray>(KMPXMessageArrayContents);
+ User::LeaveIfNull(const_cast<CMPXMessageArray*>(messageArray));
+ TInt count(messageArray->Count());
+ for(TInt i=0; i<count; ++i )
+ {
+ refresh |= DoHandleCollectionChangeMessageL(*(messageArray->AtL(i)));
+ }
+ }
+ // Single message
+ //
+ else
+ {
+ refresh = DoHandleCollectionChangeMessageL(*aMessage);
+ }
+
+ // Re-open the playlist if necessary
+ //
+ if( refresh )
+ {
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionMessageL - refresh due to KMPXMessageIdItemChanged");
+ if (iAutoPlaylist)
+ {
+ iPlObs->HandleCollectionPlaylistChange(iItemIndexes.Count() > 0 ? KErrNone : KErrEof);
+ }
+ else
+ {
+ if( iPath->Levels() > 0 )
+ {
+ DoIncrementalOpenL();
+ iReopenForChange = ETrue;
+ }
+ else
+ {
+ // Path has been clipped and not playable
+ //
+ iPlObs->HandleCollectionPlaylistChange(KErrNotFound);
+ }
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL
+// -----------------------------------------------------------------------------
+//
+TBool CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL(
+ CMPXMessage& aMessage)
+ {
+ MPX_DEBUG3("-->CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL 0x%08x, iPlObs 0x%08x",
+ this, iPlObs);
+ TBool refresh(EFalse);
+ TInt affectedIndex = KErrNotFound; // index of the id that is modified
+
+ // Change event data
+ //
+ TUid collectionId( aMessage.ValueTObjectL<TUid>(KMPXMessageCollectionId) );
+
+ TMPXChangeEventType changeType =
+ aMessage.ValueTObjectL<TMPXChangeEventType>(KMPXMessageChangeEventType);
+
+ TMPXGeneralCategory category(EMPXNoCategory);
+ if( aMessage.IsSupported(KMPXMessageMediaGeneralCategory) )
+ {
+ category =
+ aMessage.ValueTObjectL<TMPXGeneralCategory>(KMPXMessageMediaGeneralCategory);
+ }
+
+ TMPXItemId itemId(0);
+ if( aMessage.IsSupported(KMPXMessageMediaGeneralId) )
+ {
+ itemId = aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaGeneralId);
+ }
+
+ TMPXItemId deprecatedId(0);
+ if (aMessage.IsSupported(KMPXMessageMediaDeprecatedId))
+ {
+ deprecatedId = aMessage.ValueTObjectL<TMPXItemId>(KMPXMessageMediaDeprecatedId);
+ }
+
+ // Check if the current item is being modified
+ //
+ TMPXItemId curItemId( iPath->Id() );
+ if( curItemId.ApproxEqual(itemId) )
+ {
+ affectedIndex = iPath->Index();
+ // Deleted
+ if( changeType == EMPXItemDeleted )
+ {
+ refresh = ETrue;
+ }
+ // Modified
+ else if( changeType == EMPXItemModified )
+ {
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- modified");
+ refresh = ETrue;
+ }
+ // else inserted should never happen
+ }
+ // Not the current item being modified, check collection path
+ // to see if the path needs to be refreshed
+ //
+ else
+ {
+ // Map Change Type
+ //
+ CMPXCollectionPath::TMPXCollectionPathChange
+ pChangeType(CMPXCollectionPath::EGroupModified);
+ if( category == EMPXPlaylist )
+ {
+ if( changeType == EMPXItemDeleted )
+ {
+ pChangeType = CMPXCollectionPath::EDeleted;
+ }
+ else
+ {
+ pChangeType = CMPXCollectionPath::EGroupModified;
+ }
+ }
+ else if( category == EMPXCollection )
+ {
+ if( changeType == EMPXItemModified )
+ {
+ pChangeType = CMPXCollectionPath::EGroupModified;
+ }
+ }
+ else if( changeType == EMPXItemInserted )
+ {
+ pChangeType = CMPXCollectionPath::EAdded;
+ }
+ else if( changeType == EMPXItemModified )
+ {
+ pChangeType = CMPXCollectionPath::EModified;
+ }
+ else if( changeType == EMPXItemDeleted )
+ {
+ pChangeType = CMPXCollectionPath::EDeleted;
+ }
+
+ // Check the collection path
+ //
+ if( iPath->Id(CMPXCollectionPath::ECollectionRoot) == collectionId.iUid )
+ {
+ TInt pUpdated = iPath->HandleChange( collectionId, itemId,
+ deprecatedId, pChangeType, affectedIndex );
+
+ if( pUpdated == CMPXCollectionPath::EPathClipped )
+ {
+ // Path clipped, playlist is no longer valid
+ //
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- path clipped");
+ Invalidate();
+ if (iPlObs)
+ {
+ iPlObs->HandleCollectionPlaylistChange(KErrEof);
+ }
+ }
+ else if( pUpdated == CMPXCollectionPath::EPathModified )
+ {
+ // Path modified, something in needs to be refreshed
+ //
+ MPX_DEBUG1("CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL -- path modified");
+ refresh = ETrue;
+ }
+ }
+ }
+
+ if (iAutoPlaylist && refresh)
+ {
+ // For autoplaylist, affected by the event.
+ // Path clip will never happen for autoplaylist
+ if (changeType == EMPXItemDeleted)
+ {
+ // item deleted in the autoplaylist, update the iPath to remove the item
+ // auso update iItemIndexes and iItemIndex
+ iPath->Remove(affectedIndex);
+ TInt itemIndex = KErrNotFound;
+ for (TInt i=0; i<iItemIndexes.Count(); i++)
+ {
+ if (iItemIndexes[i] == affectedIndex)
+ {
+ // remove the item
+ iItemIndexes.Remove(i);
+ itemIndex = i;
+ }
+ // because the item get removed, we still need to check the next item, if it's not the last
+ if (i<iItemIndexes.Count() && iItemIndexes[i] > affectedIndex)
+ {
+ //index shift
+ --iItemIndexes[i];
+ }
+ }
+ if (iItemIndexes.Count()>0)
+ {
+ // Still has items
+ if (iItemIndex == itemIndex)
+ {
+ // current item get removed, iItemIndex already move to next
+ if (iItemIndex >= iItemIndexes.Count())
+ {
+ iItemIndex = (iRepeatMode == ERepeatAll)? 0: iItemIndexes.Count()-1;
+ }
+ }
+ else if (iItemIndex > itemIndex)
+ {
+ --iItemIndex;
+ }
+ iPath->Set(iItemIndexes[iItemIndex]);
+ }
+ else
+ {
+ iItemIndex = KErrNotFound;
+ }
+ }
+ }
+
+ MPX_DEBUG4("<--CMPXCollectionPlaylist::DoHandleCollectionChangeMessageL 0x%08x, iPlObs 0x%08x, refresh %d",
+ this, iPlObs, refresh);
+ return refresh;
+ }
+
+// -----------------------------------------------------------------------------
+// Start the incremental fetching
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::DoIncrementalOpenL()
+ {
+ if(iSingleItemPlaylist)
+ {
+ return;
+ }
+ // Stop the utility first if we were fetching
+ //
+ iIncOpenUtil->Stop();
+
+ // Copy of the path
+ //
+ CMPXCollectionPath* copy = iPath->ContainerPathL();
+ CleanupStack::PushL( copy );
+
+ RArray<TMPXAttribute> attrs;
+ CleanupClosePushL( attrs );
+ TArray<TMPXAttribute> ary = attrs.Array();
+
+ // Start the utility, 2 second delays so we don't flood the collection
+ // Have some delay as playlists are often destroyed!
+ //
+ iIncOpenUtil->SetDelay( KIncrementalDelay );
+ iIncOpenUtil->StartL( *copy, ary, KIncrementalFetchSize, iPath->Index() ,
+ CMPXCollectionOpenUtility::EFetchNormal );
+ CleanupStack::PopAndDestroy( &attrs );
+ CleanupStack::PopAndDestroy( copy );
+ }
+
+// -----------------------------------------------------------------------------
+// Handle Incremental Open results
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPlaylist::DoHandleIncompleteOpenL( const CMPXMedia& aMedia, TBool aComplete)
+ {
+ MPX_FUNC("<--CMPXCollectionPlaylist::DoHandleIncompleteOpenL");
+ if (iAutoPlaylist)
+ {
+ // Fill incomplete playlist, pending until inc open is used for playlist
+ /*
+ TInt index = iPath->IndexOfId(KMPXInvalidItemId)
+ if (!=KErrNotFound)
+ {
+ }
+ */
+ }
+ else
+ {
+ CMPXCollectionPath* newPath = iIncOpenUtil->PathL();
+
+ // Re-select the previous item, if it failed then run
+ // the restore ordinal algorithm.
+ //
+ TInt index = newPath->IndexOfId(iPath->Id());
+ if( index != KErrNotFound && !iReopenForChange )
+ {
+ newPath->Set( index );
+
+ delete iPath;
+ iPath = NULL;
+ iPath = newPath;
+ }
+ else
+ {
+ delete newPath;
+
+ TBool checkValid = (index == KErrNotFound) && (iReopenForChange);
+ if ( aComplete || (!checkValid))
+ {
+ TBool checkForOpen = (index == KErrNotFound) && (!iReopenForChange);
+ if ( !checkForOpen)
+ {
+ RestoreOrdinalL ( aMedia, 0);
+ iReopenForChange = EFalse;
+ }
+ }
+ }
+ }
+ }
+// -----------------------------------------------------------------------------
+// AutoPlay
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::AutoPlay() const
+ {
+ return iAutoPlay;
+ }
+
+// -----------------------------------------------------------------------------
+// Set AutoPlay
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetAutoPlay(TBool aAutoPlay)
+ {
+ iAutoPlay = aAutoPlay;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Set single item playlist
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetSingleItemPlaylist()
+ {
+ iSingleItemPlaylist = ETrue;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Is single item playlist
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::IsSingleItemPlaylist()
+ {
+ return iSingleItemPlaylist;
+ }
+
+// -----------------------------------------------------------------------------
+// PreInitPlugin
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPlaylist::PreInitPlugin() const
+ {
+ return iPreInitPlugin;
+ }
+
+// -----------------------------------------------------------------------------
+// Set AutoPlay
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPlaylist::SetPreInitPlugin(TBool aPreInitPlugin)
+ {
+ iPreInitPlugin = aPreInitPlugin;
+ }
+
+
+// End of file