mpx/playbackframework/playbackengine/src/mpxplaybackengine.cpp
changeset 0 a2952bb97e68
child 2 7a9a8e73f54b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/playbackframework/playbackengine/src/mpxplaybackengine.cpp	Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,3868 @@
+/*
+* 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:  Controls playback via plug-ins
+*
+*/
+
+
+#include <featmgr.h>
+#include <mpxprivatecrkeys.h>
+#include <mpxlog.h>
+#include <mpxtaskqueue.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmedia.h>
+#include <mpxcommonframeworkdefs.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxplaybackcommanddefs.h>
+#include <mpxcollectionpath.h>
+#include <mpxattributespecs.h>
+#include <mpxmessagepluginupdatedefs.h>
+#include <mpxplaybackpluginversion2.h>
+#include <mpxcmn.h>
+#include <caf/caferr.h>
+#include <mpxmediageneralextdefs.h>
+
+#include "mpxplaybacksettings.h"
+#include "mpxautoresumehandler.h"
+#include "mpxplaybackcommandbuffer.h"
+#include "mpxplaybackactiveengineobserver.h"
+#include "mpxplaybackinitializer.h"
+#include "mpxplaybackengine.h"
+#include "mpxplaybackmediahelper.h"
+#include "mpxplaybackdummymediaobserver.h"
+
+// CONSTANTS
+const TInt KMPXSmallVolumeIncrement = 5;
+const TInt KMPXLargeVolumeIncrement = 10;
+const TInt KPercentMultiplier = 100;
+_LIT(KWmaExtension, ".wma");
+_LIT(KRaExtension, ".ra");
+
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXPlaybackEngine* CMPXPlaybackEngine::NewL(
+    CMPXPluginMonitor& aPluginMonitor,
+    MMPXPlaybackActiveEngineObserver& aObserver,
+    MMPXClientlistObserver* aClientListObserver,
+    const TUid& aModeId)
+    {
+    CMPXPlaybackEngine* p=new(ELeave)CMPXPlaybackEngine(aPluginMonitor,
+                                                        aObserver, aModeId);
+    CleanupStack::PushL(p);
+    p->ConstructL(aClientListObserver);
+    CleanupStack::Pop(p);
+    return p;
+    }
+
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXPlaybackEngine* CMPXPlaybackEngine::NewL(
+    CMPXPluginMonitor& aPluginMonitor,
+    MMPXPlaybackActiveEngineObserver& aObserver,
+    MMPXClientlistObserver* aClientListObserver,
+    const TUid& aModeId,
+    const TInt aCategory)
+    {
+    CMPXPlaybackEngine* p=new(ELeave)CMPXPlaybackEngine(aPluginMonitor,
+                                                        aObserver, aModeId, aCategory);
+    CleanupStack::PushL(p);
+    p->ConstructL(aClientListObserver);
+    CleanupStack::Pop(p);
+    return p;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXPlaybackEngine::CMPXPlaybackEngine(
+    CMPXPluginMonitor& aPluginMonitor,
+    MMPXPlaybackActiveEngineObserver& aObserver,
+    const TUid& aModeId)
+:   iReflector(*this),
+    iPluginMonitor(aPluginMonitor),
+    iItemId(KMPXInvalidItemId),
+    iPlaySource(EPlayNone),
+    iAccessPoint(0),
+    iAccessPointSet(EFalse),
+    iState(EPbStateNotInitialised),
+    iNextState(EPbStateNotInitialised),
+    iPluginState(EPbStateNotInitialised),
+    iModeId(aModeId),
+    iObserver(aObserver),
+    iPreservedState( EPbStateNotInitialised ),
+    iPreservedPosition( KErrNotFound ),
+    iSkipping(EFalse),
+    iPluginUid(KNullUid),
+    iLastActiveProcess(KNullProcessId),
+    iLastInactiveProcess(KNullProcessId)
+    {
+    iProperties[EPbPropertyVolumeRamp]=KPbFadeInDurationMicroSeconds;
+    }
+
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXPlaybackEngine::CMPXPlaybackEngine(
+    CMPXPluginMonitor& aPluginMonitor,
+    MMPXPlaybackActiveEngineObserver& aObserver,
+    const TUid& aModeId,
+    const TInt aCategory)
+:   iReflector(*this),
+    iPluginMonitor(aPluginMonitor),
+    iItemId(KMPXInvalidItemId),
+    iPlaySource(EPlayNone),
+    iAccessPoint(0),
+    iAccessPointSet(EFalse),
+    iState(EPbStateNotInitialised),
+    iNextState(EPbStateNotInitialised),
+    iPluginState(EPbStateNotInitialised),
+    iModeId(aModeId),
+    iObserver(aObserver),
+    iPreservedState( EPbStateNotInitialised ),
+    iPreservedPosition( KErrNotFound ),
+    iSkipping(EFalse),
+    iPluginUid(KNullUid),
+    iLastActiveProcess(KNullProcessId),
+    iLastInactiveProcess(KNullProcessId),
+    iCategory(aCategory)
+    {
+    iProperties[EPbPropertyVolumeRamp]=KPbFadeInDurationMicroSeconds;
+    }
+
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::ConstructL(MMPXClientlistObserver* aClientListObserver)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::ConstructL");
+    iClientList=CMPXClientList::NewL(aClientListObserver);
+    iPluginHandler=CMPXPlaybackPluginHandler::NewL(iPluginMonitor, *this, *this);
+    iCmdBuffer=CMPXPlaybackCmdBuffer::NewL(*this);
+    iProgressTimer=CHeartbeat::NewL(CActive::EPriorityStandard);
+    iSeekTimer=CPeriodic::NewL(CActive::EPriorityStandard);
+    iAccessoryObs=CMPXAccessoryObserver::NewL(*this);
+    iAutoResumeHandler = CMPXAutoResumeHandler::NewL(*this, EFalse);
+    iPlaybackSettings = CMPXPlaybackSettings::NewL();
+    iTaskQueue = CMPXActiveTaskQueue::NewL();
+    FeatureManager::InitializeLibL();
+
+#if defined(__HIGH_RESOLUTION_VOLUME)
+    // Intialise volume level increment based on the accessory plugged in.
+    SetVolumeIncrement( iAccessoryObs->AccessoryModeL() );
+#else
+    iVolumeIncrement = KMPXLargeVolumeIncrement;
+#endif
+
+    iMediaHelper = CMPXPlaybackMediaHelper::NewL( *this );
+    iDummyMediaObserver = new(ELeave) CMPXPlaybackDummyMediaObserver();
+    // Select local plugin by default if none selected
+    iPluginHandler->SelectPlayersL( EPbLocal );
+    iInitVolume = ETrue;
+#if defined(__HIGH_RESOLUTION_VOLUME)
+    iVolRoundedUp = EFalse;
+#endif
+    iPluginHandler->Plugin()->PropertyL( EPbPropertyVolume );
+    }
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXPlaybackEngine::~CMPXPlaybackEngine()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::~CMPXPlaybackEngine");
+    if (iPluginHandler->Plugin())
+        {
+        iPluginHandler->Plugin()->CancelRequest();
+        }
+
+    DoClose();
+
+    if (iTaskQueue)
+        {
+        delete iTaskQueue;
+        }
+
+    if (iProgressTimer)
+        {
+        delete iProgressTimer;
+        }
+
+    if (iSeekTimer)
+        {
+        delete iSeekTimer;
+        }
+
+    FeatureManager::UnInitializeLib();
+    iFile.Close();
+    delete iCmdBuffer;
+    delete iAccessoryObs;
+    delete iAutoResumeHandler;
+    delete iPluginHandler;
+    delete iClientList;
+    delete iPlaybackSettings;
+    delete iInitializer;
+    iMediaAttrs.Close();
+    delete iMediaHelper;
+    delete iDummyMediaObserver;
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+    iFile64.Close();
+#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from collection
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitL(
+    const CMPXCollectionPlaylist& aPlaylist,
+    TBool aPlay )
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitL");
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext = aPlaylist.PreInitPlugin();
+    if ( iInitNext )
+        {
+        if ( !iInitializer )
+            {
+            iInitializer=CMPXPlaybackInitializer::NewL(*this, *iMediaHelper);
+            }
+        iInitializer->Close();
+        }
+
+    HandleCloseL();
+    iPlaySource=EPlayFromCollection;
+    iPlaylist=CMPXCollectionPlaylist::NewL(aPlaylist, this);
+    CMPXCollectionPlaylist::TRepeatMode repeatmode =
+            static_cast<CMPXCollectionPlaylist::TRepeatMode>(
+                    iProperties[EPbPropertyRepeatMode]);
+    iPlaylist->SetRepeatMode(repeatmode);
+    // if current index is not 0, play the selected item, otherwise play any one
+    iPlaylist->SetShuffleL(iProperties[EPbPropertyRandomMode],
+                           iPlaylist->Index()!=-1);
+    iSkipping = EFalse;
+    if ( aPlay )
+        {
+        if ( iPlaylist->Count() > 0 )
+            {
+            iNextState=EPbStateNotInitialised;
+            MediaFromCollectionL();
+            }
+        }
+    else
+        {
+        if ( iPlaylist->Count() > 0 )
+            {
+            iState = EPbStateStopped;
+            }
+        else
+            {
+            iState = EPbStateNotInitialised;
+            }
+        iAutoResumeHandler->HandlePlaybackStateChange(iState);
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+        iNextState = iState;
+        //update now playing view
+        iClientList->SendMsgL(TMPXPlaybackMessage(
+                TMPXPlaybackMessage::EPlaylistUpdated));
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(
+                TMPXPlaybackMessage::EInitializeComplete,
+                0,
+                EFalse));
+
+        iPluginUid = iPluginHandler->Plugin()->Uid();
+
+        RArray<TMPXAttribute> dummy;
+        CleanupClosePushL( dummy );
+        dummy.AppendL( KMPXMediaGeneralUri ); // dummy attribute to get
+        iPlaylist->MediaL( dummy.Array(), *iDummyMediaObserver);
+        CleanupStack::PopAndDestroy( &dummy );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from URI
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitL(const TDesC& aUri,const TDesC8& aType)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitL(const TDesC& aUri,const TDesC8& aType)");
+    MPX_DEBUG2("CMPXPlaybackEngine::InitL(%S)", &aUri);
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromUri;
+    iNextState=EPbStateNotInitialised;
+    delete iUri;
+    iUri = NULL;
+    iUri=aUri.AllocL();
+    iItemId = KMPXInvalidItemId;
+    TRAPD( err, InitL(&aUri,&aType,NULL) );
+    if ( KErrNotFound == err || KErrPathNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from file.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitL(const RFile& aFile)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitL(const RFile& aFile)");
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromFile;
+    iNextState=EPbStateNotInitialised;
+    iFile.Duplicate(aFile);
+    TRAPD( err, InitL(NULL,NULL,&iFile) );
+    if ( KErrNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from URI
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitStreamingL(const TDesC& aUri, const TDesC8& aType, const TInt aAccessPoint)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitStreamingL(const TDesC& aUri, const TInt aAccessPoint)");
+    MPX_DEBUG4("CMPXPlaybackEngine::InitStreamingL(%S), (%s), (%d)", &aUri, &aType, aAccessPoint);
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromUri;
+    iNextState=EPbStateNotInitialised;
+    delete iUri;
+    iUri = NULL;
+    iUri=aUri.AllocL();
+    iItemId = KMPXInvalidItemId;
+    iAccessPoint = aAccessPoint;
+    iAccessPointSet = ETrue;
+    TRAPD( err, InitL(&aUri,&aType,NULL,aAccessPoint) );
+    if ( KErrNotFound == err || KErrPathNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from file.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitStreamingL(const RFile& aFile, const TInt aAccessPoint)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitStreamingL(const RFile& aFile, const TInt aAccessPoint)");
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromFile;
+    iNextState=EPbStateNotInitialised;
+    iFile.Duplicate(aFile);
+    iAccessPoint = aAccessPoint;
+    iAccessPointSet = ETrue;
+    TRAPD( err, InitL(NULL,NULL,&iFile,aAccessPoint));
+    if ( KErrNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Cancels all outsatnding calls (tasks): plug-in should only have one
+// outstanding so that is canceled; the tasks are deleted and removed from the
+//  queue
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::CancelRequests()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::CancelRequests()");
+    CMPXPlaybackPlugin* p(iPluginHandler->Plugin());
+    if (iCallback && iTaskQueue->PtrData())
+        { // there is outstanding request
+        p = static_cast<CMPXPlaybackPlugin*>(iTaskQueue->PtrData());
+        }
+    if (p)
+        {
+        p->CancelRequest();
+        if (iCallback)
+            {
+            iTaskQueue->CompleteTask();
+            iCallback = NULL;
+            }
+        }
+    if (iPlaylist)
+        {
+        iPlaylist->CancelRequest();
+        }
+    if (iInitializer)
+        {
+        iInitializer->Close();
+        }
+    iTaskQueue->CancelRequests();
+    iMediaHelper->CancelRequests();
+    }
+
+// ----------------------------------------------------------------------------
+// Handle a command
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::CommandL(TMPXPlaybackCommand aCmd,
+                                           TInt aData)
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::CommandL(%d) entering", aCmd);
+    iClientList->SendMsgL(TMPXPlaybackMessage(
+                            TMPXPlaybackMessage::ECommandReceived,
+                            aCmd,
+                            0));
+    if (iCmdBuffer->CommandForBuffering(aCmd))
+        {
+        // Buffered commands are not valid if there are no items in playlist
+        TBool cmdOK( ETrue );
+        if ( iPlaySource == EPlayFromCollection )
+            {
+            if ( iPlaylist )
+                {
+                cmdOK = ( iPlaylist->Count() > 0 );
+                }
+            else
+                {
+                cmdOK = EFalse;
+                }
+            }
+        if ( cmdOK )
+            {
+            iCmdBuffer->BufferCommandL(aCmd,iNextState,
+                                       iProperties[EPbPropertyPosition]);
+            }
+        }
+    else
+        {
+        HandleCommandL(aCmd,aData);
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::CommandL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle a command
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::CommandL(
+    CMPXCommand& aCmd,
+    const CMPXMessageQueue& aMsgQueue )
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::CommandL(CMPXCommand& aCmd)");
+    ASSERT(aCmd.IsSupported(KMPXCommandGeneralId));
+    TInt id = aCmd.ValueTObjectL<TInt>(KMPXCommandGeneralId);
+    switch (id)
+        {
+        case KMPXCommandIdPlaybackGeneral:
+            {
+            ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralType));
+            TMPXPlaybackCommand cmd = static_cast<TMPXPlaybackCommand>(
+                        aCmd.ValueTObjectL<TInt>(KMPXCommandPlaybackGeneralType));
+            if ( EPbCmdPlay == cmd ||
+                    EPbCmdPlayPause == cmd ||
+                    EPbCmdStop == cmd)
+                {
+                ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid));
+                iLastActiveProcess = aCmd.ValueTObjectL<TProcessId>(
+                                           KMPXCommandPlaybackGeneralClientPid);
+                }
+            else if (EPbCmdStop == cmd)
+                {
+                ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralClientPid));
+                iLastInactiveProcess = aCmd.ValueTObjectL<TProcessId>(
+                                           KMPXCommandPlaybackGeneralClientPid);
+                }
+            TInt data(0);
+            if (aCmd.IsSupported(KMPXCommandPlaybackGeneralData))
+                {
+                data = aCmd.ValueTObjectL<TInt>(KMPXCommandPlaybackGeneralData);
+                }
+            MPX_DEBUG3("CMPXPlaybackEngine::CommandL general command (%d) data %d ",
+                       cmd, data);
+            // Check if command is to be buffered, if not then handle command directly
+            TBool noBuffer( EFalse );
+            if ( aCmd.IsSupported( KMPXCommandPlaybackGeneralNoBuffer ))
+                {
+                noBuffer = aCmd.ValueTObjectL<TBool>(
+                                        KMPXCommandPlaybackGeneralNoBuffer );
+                }
+
+            if ( noBuffer )
+                {
+                HandleCommandL( cmd, data );
+                }
+            else
+                {
+                // Map to TMPXCommand command
+                CommandL(cmd, data);
+                }
+            break;
+            }
+        case KMPXCommandSubscriptionAdd:
+            {
+            TInt index( iClientList->Find( aMsgQueue ));
+            CMPXMediaArray* items(
+                aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
+            User::LeaveIfNull(items);
+            CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
+             CleanupStack::PushL(subscription);
+             iClientList->AddSubscriptionL( index, subscription );   // ownership transferred
+             CleanupStack::Pop(subscription);
+            break;
+            }
+        case KMPXCommandSubscriptionRemove:
+            {
+            TInt index( iClientList->Find( aMsgQueue ));
+            CMPXMediaArray* items(
+                aCmd.Value<CMPXMediaArray>( KMPXCommandSubscriptionAddItems ));
+            User::LeaveIfNull(items);
+            CMPXSubscription* subscription( CMPXSubscription::NewL( *items ));
+             CleanupStack::PushL(subscription);
+             iClientList->RemoveSubscriptionL( index, *subscription );
+             CleanupStack::PopAndDestroy(subscription);
+            break;
+            }
+        case KMPXCommandSubscriptionRemoveAll:
+            {
+            TInt index( iClientList->Find( aMsgQueue ));
+             iClientList->RemoveAllSubscriptionsL( index );
+            break;
+            }
+
+        default:
+            {
+            // Custom command, so just send to plugin to handle
+            if ( iPluginHandler->Plugin() )
+                {
+                iPluginHandler->Plugin()->CommandL( aCmd );
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Set a property
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::SetL(TMPXPlaybackProperty aProperty,
+                                       TInt aValue)
+    {
+    MPX_DEBUG3("-->CMPXPlaybackEngine::SetL(%d, %d)", aProperty, aValue);
+    if ( aProperty < 0 || aProperty > EPbPropertyNum )
+        {
+        MPX_DEBUG1("CMPXPlaybackEngine::SetL(): Invalid Argument");
+        User::Leave( KErrArgument );
+        }
+    switch(aProperty)
+        {
+        case EPbPropertyEmbeddedMode:
+        case EPbPropertyCrossFade:
+            if ( aProperty < iProperties.Count() )
+                {
+                iProperties[aProperty]=aValue;
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                    aProperty, iProperties[aProperty]));
+                }
+            break;
+        case EPbPropertyVolume:
+            MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyVolume %d", aValue );
+            if ( aValue >= KPbPlaybackVolumeLevelMin &&
+                 aValue <= KPbPlaybackVolumeLevelMax)
+                {
+                iProperties[EPbPropertyMute] = EFalse;
+                iProperties[aProperty] = aValue;
+                if ( iPluginHandler->Plugin() )
+                    {
+                    PluginL()->SetL( aProperty, aValue );
+                    }
+#if defined(__HIGH_RESOLUTION_VOLUME)
+                iVolRoundedUp = EFalse;
+#endif                	
+                }
+            else
+                {
+                User::Leave(KErrArgument);
+                }
+            break;
+        case EPbPropertyMute:
+            MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyMute %d", aValue );
+            if ( iPluginHandler->Plugin() )
+                {
+                PluginL()->SetL( aProperty, aValue );
+                }
+            break;
+        case EPbPropertyRandomMode:
+        	{
+            MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyRandomMode %d", aValue );
+            TBool randomMode = static_cast<TBool>(aValue);
+            if( iProperties[EPbPropertyRandomMode] != randomMode )
+                {
+                iProperties[EPbPropertyRandomMode] = randomMode;
+                if (iPlaySource==EPlayFromCollection && iPlaylist)
+                    {
+                    TRAP_IGNORE(iPlaylist->SetShuffleL(randomMode, ETrue));
+                    //  Pre-initializer needs to re-copy the new shuffle list
+                    //  from the engine
+                    if (iInitializer)
+                        {
+                        iInitializer->Close();
+                        }
+                    }
+                TRAP_IGNORE(iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyRandomMode,
+                                        randomMode)));
+                }
+            break;
+            }
+        case EPbPropertyRepeatMode:
+        	{
+            MPX_DEBUG2( "CMPXPlaybackEngine::SetL EPbPropertyRepeatMode %d", aValue );
+            TMPXPlaybackRepeatMode repeat = static_cast<TMPXPlaybackRepeatMode>(aValue);
+            if( iProperties[EPbPropertyRepeatMode] != repeat )
+                {
+                iProperties[EPbPropertyRepeatMode] = repeat;
+                if (iPlaySource==EPlayFromCollection && iPlaylist)
+                    {
+                    CMPXCollectionPlaylist::TRepeatMode repeatmode =
+                            static_cast<CMPXCollectionPlaylist::TRepeatMode>(
+                            repeat);
+                    iPlaylist->SetRepeatMode(repeatmode);
+                    if (iInitializer)
+                        {
+                        iInitializer->Close();
+                        }
+                    }
+                TRAP_IGNORE(iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyRepeatMode,
+                                        repeat)));
+                }
+            break;
+            }
+        case EPbPropertyPosition:
+            {
+            CMPXPlaybackPlugin* pi = PluginL();
+            if ( pi )
+                {
+                MPX_DEBUG2( "CMPXPlaybackEngine::SetL setting position %d", aValue );
+                iProperties[aProperty] = aValue;
+                pi->SetL(EPbPropertyPosition, aValue);
+                }
+            break;
+            }
+        default:
+            iProperties[aProperty]=aValue;
+            PluginL()->SetL(aProperty,aValue);
+        }
+    MPX_DEBUG3("<--CMPXPlaybackEngine::SetL(%d, %d)", aProperty, aValue);
+    }
+
+// ----------------------------------------------------------------------------
+// Property request
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::PropertyL(TMPXPlaybackProperty aProperty,
+                                         MMPXPlaybackEngineObserver& aCallback)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::PropertyL()");
+    MPX_DEBUG4("CMPXPlaybackEngine::PropertyL 0x%08x cb 0x%08x, prop %d",
+                this, &aCallback, aProperty);
+    if (aProperty == EPbPropertyVolume)
+        {
+        aCallback.HandleProperty(aProperty,
+                                 iProperties[EPbPropertyVolume],
+                                 KErrNone);
+        }
+    else if (aProperty == EPbPropertyMaxVolume)
+        {
+        aCallback.HandleProperty(aProperty,
+                                 KPbPlaybackVolumeLevelMax,
+                                 KErrNone);
+        }
+    else if (aProperty == EPbPropertyRandomMode)
+        {
+        TInt random(0);
+        if ( iPlaylist )
+            {
+            random = iPlaylist->Shuffle();
+            }
+        else
+            {
+            random = iProperties[EPbPropertyRandomMode];
+            }
+        aCallback.HandleProperty(aProperty,
+                                 random,
+                                 KErrNone);
+        }
+    else if (aProperty == EPbPropertyRepeatMode)
+        {
+        TInt repeat(0);
+        if ( iPlaylist )
+            {
+            repeat = iPlaylist->RepeatMode();
+            }
+        else
+            {
+            repeat = iProperties[EPbPropertyRepeatMode];
+            }
+        aCallback.HandleProperty(aProperty,
+                                 repeat,
+                                 KErrNone);
+        }
+    else if (aProperty == EPbPropertyPosition &&
+             EPbStateNotInitialised == iPluginState)
+        {
+        aCallback.HandleProperty(aProperty,
+                                 iProperties[EPbPropertyPosition],
+                                 KErrNone);
+        }
+    else
+        {
+        MPX_DEBUG1("CMPXPlaybackEngine::PropertyL add request to task queue");
+        iTaskQueue->AddTaskL(EProperty, &aCallback, this, aProperty);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Async call: must be added to task queue
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::MediaL(
+    MMPXPlaybackEngineObserver& aCallback,
+    CBufBase* /*aBuf*/)
+    {
+    MPX_DEBUG3("-->CMPXPlaybackEngine::MediaL() aBuf 0x%08x cb 0x%08x", this, &aCallback);
+    // DEPRECATED
+    MPX_ASSERT( 0 );
+    MPX_DEBUG2("<--CMPXPlaybackEngine::MediaL() aBuf 0x%08x", this);
+    }
+
+// ----------------------------------------------------------------------------
+// Async call: must be added to task queue
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::MediaL(
+    MMPXPlaybackEngineObserver& aCallback,
+    const CMPXCommand& aCmd)
+    {
+    MPX_DEBUG3("-->CMPXPlaybackEngine::MediaL() aCmd 0x%08x cb 0x%08x", this, &aCallback);
+    CMPXCommand* cmd( CMPXCommand::NewL( aCmd ) );
+    CleanupStack::PushL( cmd );
+    TBool redirect = EFalse;    
+    if (CMPXAttributeSpecs* specs = aCmd.Value<CMPXAttributeSpecs>( KMPXCommandMediaAttributeSpecs ))
+        { 
+        if (specs->IsSupported(KMPXMediaGeneralExtMediaRedirect))
+             {
+             redirect = ETrue;
+             MPX_DEBUG1("CMPXPlaybackEngine::MediaL - Redirect to Playback Plugin");
+             }        
+        }
+    
+    // If redirect is false, pass the cmd to mediahelper class
+    if ( iPlaySource == EPlayFromCollection && iPlaylist && !redirect)
+        {
+        // Onwership of cmd is passed to mediahelper class
+        iMediaHelper->MediaL( iPlaylist->Path(), cmd, &aCallback );
+        }
+    else
+        {
+        // ownership of cmd is transfered
+        MediaFromPluginL( &aCallback, cmd );
+        }
+    CleanupStack::Pop( cmd );
+    MPX_DEBUG2("<--CMPXPlaybackEngine::MediaL() aCmd 0x%08x", this);
+    }
+
+// ----------------------------------------------------------------------------
+// Async call: must be added to task queue
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::SubPlayerNamesL(TUid aPlayerUid,
+                                                  MMPXPlaybackEngineObserver& aCallback)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::SubPlayerNamesL()");
+    CMPXPlaybackPlugin* p = iPluginHandler->CreatePlayerPluginL(aPlayerUid);
+    iTaskQueue->AddTaskL(ESubPlayerNames,&aCallback, this, aPlayerUid.iUid, NULL, p);
+    }
+
+// ----------------------------------------------------------------------------
+// Async call: must be added to task queue
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::MediaFromPluginL(
+    MMPXPlaybackEngineObserver* aCallback,
+    CMPXCommand* aCmd )
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::MediaFromPluginL");
+    CleanupStack::PushL( aCmd );
+    iTaskQueue->AddTaskL( EMedia, aCallback, this, 0, NULL, NULL, aCmd );
+    CleanupStack::Pop( aCmd ); // Ownership transferred to the task queue
+    }
+
+// ----------------------------------------------------------------------------
+// Handles a regular heartbeat timer event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::Beat()
+    {
+        
+    // retrieve position from plugins directly
+    if (iState != EPbStatePlaying)
+        {
+        iProgressTimer->Cancel();
+        }
+    else
+        {
+        TRAP_IGNORE(iTaskQueue->AddTaskL(EProperty, &iReflector,
+                                         this, EPbPropertyPosition));
+        }
+
+    }
+
+// ----------------------------------------------------------------------------
+// Synchronises the heartbeat timer with system clock
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::Synchronize()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::Synchronize");
+    MPX_DEBUG2("CMPXPlaybackEngine::Synchronize(): iState = %d", iState);
+        
+    // do the same thing as Beat
+    Beat();
+    }
+
+// ----------------------------------------------------------------------------
+// Handle accessory event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleAccesoryEventL(TMPXPlaybackAccessoryMode aMode)
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::HandleAccesoryEventL(%d) entering", aMode);
+    iClientList->SendMsgL(
+        TMPXPlaybackMessage( TMPXPlaybackMessage::EAccessoryChanged,
+                             aMode,
+                             0));
+
+#if defined(__HIGH_RESOLUTION_VOLUME)
+    SetVolumeIncrement( aMode );
+#endif // HIGH_RESOLUTION_VOLUME
+
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleAccesoryEventL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Callback from plug-in, handle plugin event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePluginEvent(
+    TEvent aEvent,
+    TInt aData,
+    TInt aError)
+    {
+    TRAP_IGNORE(DoHandlePluginEventL(aEvent, aData, aError));
+    }
+
+// ----------------------------------------------------------------------------
+// Callback from plug-in, handle plugin message
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePlaybackMessage(
+    CMPXMessage* aMsg,
+    TInt aErr)
+    {
+    iClientList->SendMsg(aMsg, aErr);
+    }
+
+// ----------------------------------------------------------------------------
+// Handler plugin event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::DoHandlePluginEventL(
+    TEvent aEvent,
+    TInt aData,
+    TInt aError)
+    {
+    MPX_DEBUG5("-->CMPXPlaybackEngine::DoHandlePluginEventL 0x%08x, event %d, data %d, error %d.",
+               this, aEvent, aData, aError);
+
+    TInt disconnectionError = aError;
+    if ( aEvent == EPPlayerUnavailable )
+        {
+        aError = KErrNone;
+        }
+
+    if (aError!=KErrNone)
+        {
+        // If error occured during pause event, change to pause but also
+        // send error code to clients to handle
+        if ( aEvent == EPPaused )
+            {
+            MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL(): Pause Error = %d", aError);
+
+            if ( aError != KErrNotSupported )
+                {
+                // If error during seeking event, keep seeking and set
+                // plugin state to not intialised
+                if ( iState == EPbStateSeekingForward ||
+                     iState == EPbStateSeekingBackward )
+                    {
+                    iPluginState = EPbStateNotInitialised;
+                    }
+                else
+                    {
+                    iState = EPbStatePaused;
+                    iNextState = EPbStatePaused;
+                    SetPlayerActivated(EFalse);
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(
+                            TMPXPlaybackMessage::EStateChanged, iState, aError ));
+                    if ( KErrDied == aError ||
+                         KErrAccessDenied == aError )
+                        {
+                        iPluginState = EPbStateNotInitialised;
+                        // fixed 
+                        iAutoResumeHandler->HandlePlaybackComplete(aError);
+                        iAutoResumeHandler->HandlePlaybackStateChange(iState);
+
+                        }
+                    }
+                }
+            else // Pause functionality is not supported, no change of state
+                 // we just send the error back to Ui to let the user know
+                {
+                iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged, aEvent, aError));
+
+                TMPXPlaybackState s = EPbStatePlaying;
+                iNextState = EPbStatePlaying;
+
+                // Set state first before activation, since activation
+                // will send a state changed update event as well
+                SetStateL(s);
+                }
+            }
+        else if ( aEvent != EPSetComplete ) //Not paused and not EPSetComplete
+            { // sometimes upnp failed to set value.
+            MPX_DEBUG4("CMPXPlaybackEngine::DoHandlePluginEventL error aError %d, iState %d, iNextState %d",
+                       aError, iState, iNextState );
+            SavePlaybackInfoL();
+            HandlePluginEventErrorHandling(aEvent, aError);
+            iState = EPbStateStopped;
+            iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+            if (aError)
+                {
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EError,aEvent,aError));
+                }
+            }
+        else // SetComplete
+            {
+            if ( aError == KErrNotSupported &&
+                 aData == EPbPropertyVolume )
+                {
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        aData, aError));
+                }
+            }
+        }
+    else // No errors
+        {
+        MPX_DEBUG4("CMPXPlaybackEngine::DoHandlePluginEventL, iState %d, iNextState %d, iSkipping %d",
+                   iState, iNextState, iSkipping );
+
+        switch(aEvent)
+            {
+            case EPInitialised:
+            case EPClosed:
+            case EPPaused:
+            case EPPlaying:
+            case EPStopped:
+            case EPDownloadPositionChanged:
+            case EPDownloadStateChanged:
+            case EPDownloadCmdPauseDownload:
+            case EPDownloadCmdResumeDownload:
+            case EPDownloadCmdCancelDownload:
+            case EPDownloadStarted:
+            case EPDownloadingUpdated:
+            case EPDownloadingComplete:	
+            case EPBufferingStarted:
+            case EPPlayComplete:  
+            case EPPluginSeeking:          	
+            	{
+            	UpdateStateMachineL(aEvent, aData, aError);
+            	break;
+            	}    
+            case EPActive:
+                {
+                MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL active message.");
+                SetPlayerActivated(aData);
+                break;
+                }
+            case EPSubPlayersChanged:
+                {
+                MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL subplayer changed.");
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::ESubPlayersChanged));
+                break;
+                }
+            case EPSupportedFeaturesChanged:
+                {
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                       EPbPropertySupportedFeatures, aData));
+                break;
+                }
+            case EPSetComplete:
+                {
+                if ( aData < iProperties.Count() )
+                    {
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                            aData, iProperties[aData]));
+                    }
+                break;
+                }
+            case EPDurationChanged:
+                {
+                iProperties[EPbPropertyDuration]=aData;
+                SetPropertiesL();
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyDuration,
+                                        iProperties[EPbPropertyDuration]));
+                break;
+                }
+            case EPPlayerUnavailable:
+                {
+                if (iInitializer)
+                    {
+                    iInitializer->Close();
+                    }
+                SavePlaybackInfoL();
+                iPreservedState = iState;
+                iPreservedPosition = iProperties[EPbPropertyPosition];
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerUnavailable,
+                                        0, disconnectionError));
+                break;
+                }
+            case EPVolumeChanged:
+                {
+                iProperties[EPbPropertyVolume] = aData;
+                if (iInitVolume)
+                    {
+                    iInitVolume = EFalse;
+                    }
+                else
+                    {
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                            EPbPropertyVolume,
+                                            iProperties[EPbPropertyVolume]));
+                    }
+                break;
+                }
+            case EPMuteChanged:
+                {
+                if ( iProperties[EPbPropertyMute] != aData )
+                    {
+                    iProperties[EPbPropertyMute] = aData;
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                            EPbPropertyMute,
+                                            iProperties[EPbPropertyMute]));
+                    }
+                break;
+                }
+            case EPPositionChanged:
+                {
+                iProperties[EPbPropertyPosition] = aData;
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyPosition,
+                                        iProperties[EPbPropertyPosition]));
+                break;
+                }
+            case EPDownloadFileMoved:
+                {
+                CMPXMessage* msg = CMPXMessage::NewL();
+                CleanupStack::PushL(msg);
+                TMPXMessageId id=static_cast<TMPXMessageId>(KMPXMessageGeneral);
+                HBufC* path = reinterpret_cast<HBufC*>(aData);
+                msg->SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, id);
+                msg->SetTObjectValueL<TInt>(KMPXMessageGeneralEvent, TMPXPlaybackMessage::EDownloadFileMoved);
+                msg->SetTObjectValueL<TInt>(KMPXMessageGeneralType, 0);
+                msg->SetTObjectValueL<TInt>(KMPXMessageGeneralData, 0);
+                msg->SetTextValueL( KMPXMediaGeneralUri, *path );
+                iClientList->SendMsg(msg, KErrNone);
+                CleanupStack::PopAndDestroy( msg );
+                break;
+                }
+            default:
+                ASSERT(0);
+            }
+        }
+    MPX_DEBUG2("<--CMPXPlaybackEngine::DoHandlePluginEventL() 0x%08x", this);
+    }
+
+// ----------------------------------------------------------------------------
+// Update State Machine
+// Handle plugin events that could cause state change in playback-engine
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::UpdateStateMachineL(
+	    TEvent aEvent,
+	    TInt aData,
+	    TInt aError)
+	{
+	MPX_DEBUG4("CMPXPlaybackEngine::UpdateStateMachine, iState %d, iNextState %d, iSkipping %d",
+	           iState, iNextState, iSkipping );
+
+	TMPXPlaybackState s=iState;
+
+	switch(aEvent)
+	    {
+        case EPInitialised:
+            {
+            HandlePluginEventInitialisedL( s, aData );
+            break;
+            }            
+	    case EPPlaying:
+	        {
+	        s = EPbStatePlaying;
+	        iNextState = EPbStatePlaying;
+	        MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL playing.");
+	
+	        // Set state first before activation, since activation
+	        // will send a state changed update event as well
+	        SetStateL(s);
+	        SetPlayerActivated(ETrue);
+	        iPluginState = EPbStatePlaying;
+	        break;
+	        }            
+	    case EPClosed:
+	        {
+	        MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL closed.");
+	        MPX_DEBUG2("CMPXPlaybackEngine::HandlePluginEventL: iState = %d", iState);
+
+	        iPluginState = EPbStateNotInitialised;
+
+	        // Do not set state changed event when initialising
+	        if ( iState != EPbStateInitialising && EPbCmdClose == aData)
+	            {
+	            s=EPbStateNotInitialised;
+
+	            // Set state first before deactivation, since deactivation
+	            // will send a state changed update event as well
+	            SetStateL(s);
+	            SetPlayerActivated(EFalse);
+	            } // else close when stop
+	        break;
+	        }
+	    case EPPaused:
+	        {
+	        if (iState != EPbStateSeekingForward &&
+	            iState != EPbStateSeekingBackward &&
+	            iState != EPbStatePaused &&
+	            !iSkipping)
+	            {
+	            s=EPbStatePaused;
+
+	            if (EPbStatePlaying == iNextState)
+	                { // only change state from playing to pause
+	                iNextState = EPbStatePaused;
+	                }
+
+	            MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL paused.");
+	
+	            // Set state first before deactivation, since deactivation
+	            // will send a state changed update event as well
+	            SetStateL(s);
+	            SetPlayerActivated(EFalse);
+	            }
+
+	        iPluginState = EPbStatePaused;
+	        break;
+	        }
+	    case EPActive:
+	        {
+	        MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL active message.");
+	        SetPlayerActivated(aData);
+	        break;
+	        }            
+	    case EPStopped:
+	        {
+	        MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL stopped.");
+
+	        s = EPbStateStopped;
+	        SetStateL(s);
+	        TBool handleStop(EFalse);
+
+	        if (iState != EPbStateSeekingForward &&
+	            iState != EPbStateSeekingBackward &&
+	            !iSkipping &&
+	            iNextState != EPbStatePlaying)
+	            {
+	            handleStop = ETrue;
+	            }
+	        else if (iProgressTimer->IsActive())
+	            { // stop from remote player
+	            Suspend();
+	            iNextState = EPbStateStopped;
+	            handleStop = ETrue;
+	            } // else stop for seeking
+	        if (handleStop)
+	            {
+	            SetPlayerActivated( EFalse );
+	            s=EPbStateStopped;
+	            if ( iProperties[EPbPropertyPosition] != 0 )
+	                {
+	                iProperties[EPbPropertyPosition]=0;
+	                iClientList->SendMsgL(
+	                    TMPXPlaybackMessage(
+	                        TMPXPlaybackMessage::EPropertyChanged,
+	                        EPbPropertyPosition,
+	                        0 ));
+	                }
+	            }
+	        break;
+	        }
+        case EPPlayComplete:
+            {
+            EndSeek();
+            SavePlaybackCompleteInfoL();
+            iAutoResumeHandler->HandlePlaybackComplete(aError);
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                    EPbPropertyPosition,
+                                    iProperties[EPbPropertyDuration]));
+            iTaskQueue->AddTaskL(EHandleNext, NULL, this, 0);
+            s=EPbStateStopped; 	//State Changed indication Stopped will be sent           
+            break;
+        	}
+        case EPDownloadPositionChanged:
+            {
+            if ( EPbStateInitialising == s )
+                {
+                s=EPbStateBuffering;
+                }
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadPositionChanged,
+                                     0,
+                                     aData ));
+            break;
+            }
+        case EPDownloadStateChanged:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadStateChanged,
+                                     0,
+                                     aData ));
+            break;
+            }
+        case EPDownloadCmdPauseDownload:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdPauseDownload,
+                                     0,
+                                     aData ));
+            break;
+            }
+        case EPDownloadCmdResumeDownload:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdResumeDownload,
+                                     0,
+                                     aData ));
+            break;
+            }
+        case EPDownloadCmdCancelDownload:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadCmdCancelDownload,
+                                     0,
+                                     aData ));
+            break;
+            }
+        case EPDownloadStarted:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::EDownloadStarted,
+                                     0,
+                                     aData));
+            break;
+            }
+        case EPDownloadingUpdated:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EDownloadUpdated,
+                                    0,aData));
+            s=EPbStateDownloading;
+            break;
+            }
+            // end comment this later
+        case EPDownloadingComplete:
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EDownloadComplete,
+                                    0,aData));
+            s=EPbStateStopped;
+
+            if ( iProperties[EPbPropertyPosition] != 0 )
+                {
+                iProperties[EPbPropertyPosition]=0;
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(
+                        TMPXPlaybackMessage::EPropertyChanged,
+                        EPbPropertyPosition,
+                        0 ));
+                }
+            break;
+            }
+        case EPBufferingStarted:
+        	{
+        	s = EPbStateBuffering;
+            iPluginState = EPbStatePlaying;	//ToDo: Do we need pluginstate?!?!?
+        	break;
+        	}
+        case EPPluginSeeking:
+          {
+           // suspend playback timer
+           Suspend();
+           // Change to plugin seeking state
+           iNextState = iState;
+           s = EPbStatePluginSeeking;
+           MPX_DEBUG1("CMPXPlaybackEngine::HandlePluginEventL EPbStatePluginSeeking.");
+
+           // Set state first before activation, since activation
+           // will send a state changed update event as well
+           SetStateL(s);
+           iPluginState = EPbStatePluginSeeking;
+           break;
+           }        
+	    }
+	SetStateL(s);				//Check if state changed and notify clients.
+    }
+
+// ----------------------------------------------------------------------------
+// Handle Plugin Event : Initialised
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePluginEventInitialisedL(TMPXPlaybackState& s, TInt aData)
+	{
+#if defined(__HIGH_RESOLUTION_VOLUME)
+// Merlin twentysteps hack start
+    if ( iUri )
+        {
+        TParsePtrC parser(*iUri);
+        
+        MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL(): iUri is %S", iUri);
+        if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0)
+            {
+            // for wma/ra file, increment is always 10 with or without headset
+            iVolumeIncrement = KMPXLargeVolumeIncrement;  
+            MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL it is a wma/ra file, volumeIncrement: %d !!!!", iVolumeIncrement); 
+            }
+        }
+#ifdef __ACCESSORY_FW
+    else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryWiredHeadset || iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadphones)
+#else        
+    else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadset)
+#endif // __ACCESSORY_FW
+        {
+        // for non wma files with headset, the volume increment is 5
+        iVolumeIncrement = KMPXSmallVolumeIncrement;
+        }
+#endif // HIGH_RESOLUTION_VOLUME    
+//  twentysteps  end                	
+                
+    iPluginState = EPbStateStopped;
+    // Reset corrupted and invalid flags if no error
+    // Only set if they were not set before, this is because
+    // calls to SetL() on collection are costly
+    MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
+    if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
+         iDbFlag & KMPXMediaGeneralFlagsIsInvalid ||
+         iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
+        {
+        TRAP_IGNORE(
+            SetFlagBitsL( EFalse,
+                          KMPXMediaGeneralFlagsIsCorrupted |
+                          KMPXMediaGeneralFlagsIsInvalid |
+                          KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
+        }
+
+    iClientList->SendMsgL(TMPXPlaybackMessage(
+                    TMPXPlaybackMessage::EMediaChanged));
+
+    iProperties[EPbPropertyDuration]=aData;		//Note, radio has no duration!
+    SetPropertiesL();
+    iClientList->SendMsgL(
+        TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                            EPbPropertyDuration,
+                            iProperties[EPbPropertyDuration]));
+
+    //Assumption: we take duration==0 to mean "live streaming"
+        // Check if position is not past the duration
+	if ( iProperties[EPbPropertyPosition] >= iProperties[EPbPropertyDuration] )
+            {
+            iProperties[EPbPropertyPosition] = 0;
+            }
+
+    // Set position to restore saved position.
+    TRAP_IGNORE( // uPnP leaves if set position in stop state
+            PluginL()->SetL( EPbPropertyPosition, iProperties[EPbPropertyPosition] ));
+
+    iAutoResumeHandler->HandleOpenFileComplete();
+    
+    // Check if playback should not be started automatically.
+    if ( iAccessPoint || ( iPlaylist && (!iPlaylist->AutoPlay()) ) )
+        {
+        iNextState = EPbStateNotInitialised;
+        }
+    
+    TMPXPlaybackState nextState(iNextState); // save next state
+    switch (iNextState) //What the next state could be (command may have been sent).
+    	{
+    	case EPbStateNotInitialised:
+            { // Notify client initialized complete         
+            MPX_DEBUG1("CMPXPlaybackEngine sends msg EInitializeComplete");
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(
+                    TMPXPlaybackMessage::EInitializeComplete,
+                    0,
+                    ETrue));
+            s = EPbStateInitialised;	//This will cause a StateChanged message to be sent          
+            break;
+            }
+    	case EPbStateStopped:
+            { // Play to the end of playlist
+            PluginL()->CommandL(EPbCmdStop);
+            if (iInitializer)
+                { // close file in the initializer
+                iInitializer->Close();
+                }
+            s = EPbStateStopped;
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                    EPbPropertyPosition,
+                                    iProperties[EPbPropertyPosition]));
+    		break;            
+            }    		
+    	default:
+            {
+            iState = EPbStateStopped;
+            HandleCommandL(CommandFromState( iNextState ));
+            s = iState; // change to new state due to handle command
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                    EPbPropertyPosition,
+                                    iProperties[EPbPropertyPosition]));            
+    		break;            
+            }    		
+        }
+
+    if (iInitNext && EPbStateStopped != nextState)
+        {
+        //
+        // Try pre-initialsing the next song, just in case we get there
+        //
+        TBool more = iInitializer->Next();
+        if (!more && iPlaylist->Shuffle())
+            { // Reach to the end and shuffle is on, pre-initializer
+              // needs  to re-copy the new shuffle list from engine
+            if (iInitializer)
+                {
+                iInitializer->Close();
+                }
+            }
+        }
+	}
+
+// ----------------------------------------------------------------------------
+// Error handling for Handler plugin event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePluginEventErrorHandling(TEvent aEvent, TInt aError)
+	{
+	switch (aError)
+	    {
+	    case KErrGeneral:
+	        {
+	        // Track initialization failed
+	        if ( ( aEvent == EPInitialised ) ||
+	             ( aEvent == EPPlaying ) )
+	            {
+	            aError = KErrNotSupported;
+	            // Mark item as corrupted
+	
+	            // fall through on purpose
+	            }
+	        else
+	            {
+	            break;
+	            }
+	        }
+	    case KErrArgument:
+	    case KErrNotSupported:
+	    case KErrCorrupt:
+		case KErrDivideByZero:
+	        {
+	        // Release file handles
+	        TRAP_IGNORE(DoStopL());
+	        // Mark item as corrupted
+	        MarkItemCorrupted( ETrue );
+	
+	        // Reset DRM and invalid flags if they are set
+	        MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
+	        if ( iDbFlag & KMPXMediaGeneralFlagsIsInvalid ||
+	             iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
+	            {
+	            TRAP_IGNORE(
+	                SetFlagBitsL( EFalse,
+	                              KMPXMediaGeneralFlagsIsInvalid |
+	                              KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
+	            }
+	
+	        break;
+	        }
+	    case KErrNotFound:
+	        {
+	        // Mark item as invalid
+	        MarkItemInvalid( ETrue );
+	
+	        // Reset DRM and corrupted flags if they are set
+	        MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
+	        if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
+	             iDbFlag & KMPXMediaGeneralFlagsIsDrmLicenceInvalid )
+	            {
+	            TRAP_IGNORE(
+	                SetFlagBitsL( EFalse,
+	                              KMPXMediaGeneralFlagsIsCorrupted |
+	                              KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
+	            }
+	
+	        break;
+	        }
+	    case KErrCANotSupported:
+	    case KErrCANoPermission:
+	    case KErrCANoRights:
+	    case KErrCANoAgent:
+	    case KErrCAOutOfRange:
+	    case KErrCAPendingRights:
+	    case KErrCASizeNotDetermined:
+	    case KErrCANewFileHandleRequired:
+	        {
+	        // Release file handles
+	        TRAP_IGNORE(DoStopL());
+	        // Mark item as DRM Invalid
+	        MarkItemDrmInvalid( ETrue );
+	
+	        // Reset corrupted and invalid flags if they are set
+	        MPX_DEBUG2("CMPXPlaybackEngine::DoHandlePluginEventL() iDbFlag %x", iDbFlag);
+	        if ( iDbFlag & KMPXMediaGeneralFlagsIsCorrupted ||
+	             iDbFlag & KMPXMediaGeneralFlagsIsInvalid )
+	            {
+	            TRAP_IGNORE(
+	                SetFlagBitsL( EFalse,
+	                              KMPXMediaGeneralFlagsIsCorrupted |
+	                              KMPXMediaGeneralFlagsIsInvalid ));
+	            }
+	
+	
+	        break;
+	        }
+	    case KErrDied:
+	        {
+	        // Release file handles
+	        TRAP_IGNORE(DoStopL());
+	        iNextState = EPbStateNotInitialised;
+	        break;
+	        }
+	    default:
+	        // otherwise send error message to clients
+	        break;
+	    }
+	}
+
+// ----------------------------------------------------------------------------
+// Callback from plug-in. Retrieve the task that resulted in this (which
+// removes it from the queue), get the observer and call back with the results.
+// Then the player is free to execute the next task, if any
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleProperty(
+    TMPXPlaybackProperty aProperty,
+    TInt aValue,
+    TInt aError)
+    {
+    MPX_DEBUG5("-->CMPXPlaybackEngine::HandleProperty 0x%08x prop %d val %d err %d",
+               this, aProperty, aValue, aError);
+    if ( iInitVolume && EPbPropertyVolume == aProperty )
+        {
+        if (KErrNone == aError)
+            {
+            iProperties[EPbPropertyVolume] = aValue;
+            iInitVolume = EFalse;
+            }
+        }
+    else
+        {
+        ASSERT(iTaskQueue->Task() == EProperty && iTaskQueue->Callback() == iCallback);
+        iCallback->HandleProperty(aProperty,aValue,aError);
+        iCallback = NULL;
+        iTaskQueue->CompleteTask();
+        
+        // notify client the new position during the playback
+        if ((EPbPropertyPosition == aProperty) && (iProgressTimer->IsActive()))
+            {
+            TRAP_IGNORE(iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyPosition,aValue)));            
+            }
+        }
+    MPX_DEBUG2("<--CMPXPlaybackEngine::HandleProperty 0x%08x", this);
+    }
+
+// ----------------------------------------------------------------------------
+// Callback from plug-in. Retrieve the task that resulted in this (which
+// removes it from the queue), get the observer and call back with the results.
+// Then the player is free to execute the next task, if any
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleMedia(
+    CMPXMedia* aMedia,
+    TInt aError)
+    {
+    ASSERT(iTaskQueue->Task() == EMedia && iTaskQueue->Callback() == iCallback);
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandleMedia()");
+    iCallback->HandleMedia(aMedia, aError);
+    iCallback = NULL;
+    iTaskQueue->CompleteTask();
+    }
+
+// ----------------------------------------------------------------------------
+// Callback from plug-in. Retrieve the task that resulted in this (which
+// removes it from the queue), get the observer and call back with the results.
+// Then the player is free to execute the next task, if any
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleSubPlayerNames(
+    TUid /*aPlayer*/,
+    const MDesCArray* aSubPlayers,
+    TBool aComplete,
+    TInt aError)
+    {
+    ASSERT(iTaskQueue->Task() == ESubPlayerNames &&
+            iTaskQueue->Callback() == iCallback);
+    MPX_DEBUG4("-->CMPXPlaybackEngine::HandleSubPlayerNames 0x%08x, complete %d, err %d",
+               this, aComplete, aError);
+    iCallback->HandleSubPlayerNames(TUid::Uid(0), aSubPlayers,
+                                    aComplete, aError);
+    iCallback = NULL;
+    iTaskQueue->CompleteTask();
+    MPX_DEBUG2("<--CMPXPlaybackEngine::HandleSubPlayerNames 0x%08x", this);
+    }
+
+// ----------------------------------------------------------------------------
+// Handle media key event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCmdBufferEventL(const TMPXPlaybackCmdInfo& aEvent)
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() entering");
+
+    MPX_DEBUG4("CMPXPlaybackEngine::HandleCmdBufferEventL(): offset=%d, state=%d, navKeyBuffered=%d", aEvent.iTrackOffset, iNextState, aEvent.iNavKeyBuffered);
+
+    // Fix for EJPI-7BHUGX, if the aEvent.iNavKeyBuffered == 1 and aEvent.iTrackOffset == 0
+    // That means skip back key press once only, it should not request for media but set pos only
+    if ( aEvent.iNavKeyBuffered > 1 || aEvent.iTrackOffset != 0 )
+        {
+        iNextState = aEvent.iState;
+        if ( EPlayFromCollection == iPlaySource && iPlaylist )
+            {
+            MediaFromCollectionL();
+            }
+        else if ( EPlayFromUri == iPlaySource )
+            {
+            TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ) );
+            }
+        }
+    else
+        {
+        // If position has changed, set the position in plugin.
+        // Also the current position should be after the original position
+        if ( Abs(aEvent.iPos - iProperties[EPbPropertyPosition]) >
+             KPbPositionChangeThreshold &&
+             aEvent.iPos < iProperties[EPbPropertyPosition] )
+            {
+            MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL(): position changed");
+            iProperties[EPbPropertyPosition]=aEvent.iPos;
+            if ( PluginL() )
+                {
+                if (iState == EPbStatePlaying)
+                    {
+                    // Need to send pause command to plugin first so that it will
+                    // not keep playing the rest of it's buffer
+                    MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() send pause command");
+                    PluginL()->CommandL(EPbCmdPause);
+                    }
+                PluginL()->SetL(EPbPropertyPosition,
+                                iProperties[EPbPropertyPosition]);
+                }
+            }
+
+        HandleCommandL(CommandFromState( aEvent.iState ));
+        }
+    iCmdBuffer->CompleteCommand();
+
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleCmdBufferEventL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle command skip event from key buffering
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCmdBufferSkipEventL(
+    const TMPXPlaybackSkipEvent aSkipEvent )
+    {
+    MPX_DEBUG2("==>CMPXPlaybackEngine::HandleCmdBufferSkipEventL(%d) entering", aSkipEvent);
+
+    if ( EPbsSkipEventNext == aSkipEvent )
+        {
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipping, 0, 1 ));
+
+        TBool wasSkipping( iSkipping );
+        iSkipping = ETrue;
+        if ( !wasSkipping )
+            {
+            if ( iState == EPbStatePlaying )
+                {
+                Suspend();
+                TRAP_IGNORE(PluginL()->CommandL(EPbCmdPause));
+                TRAP_IGNORE(SavePlaybackInfoL());
+                }
+            else if ( iState == EPbStatePaused )
+                {
+                TRAP_IGNORE(SavePlaybackInfoL());
+                }
+            }
+        if ( EPlayFromCollection == iPlaySource && iPlaylist )
+            {
+            if ( iPlaylist->Count() > 0 )
+                {
+                // Stop if playing or paused
+                if ( !iPlaylist->Next( ETrue ) )
+                    {
+                    if ( EPbStatePlaying == iNextState ||
+                         EPbStatePaused == iNextState )
+                        {
+                        iCmdBuffer->BufferCommandL(
+                            EPbCmdStop,
+                            iNextState,
+                            iProperties[EPbPropertyPosition]);
+                        }
+                    
+                    // End of playlist, send message to clients.
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::
+                                            EReachedEndOfPlaylist));
+                    }
+                RequestMediaL();
+                }
+            }
+        }
+    else if ( EPbsSkipEventPrevious == aSkipEvent )
+        {
+        TBool wasSkipping( iSkipping );
+        iSkipping = ETrue;
+        if ( !wasSkipping && iState == EPbStatePlaying)
+            {
+            TRAP_IGNORE(DoStopL());
+            PluginL()->CommandL( EPbCmdPause );
+            }
+
+        // If first track in list and repeat is off, it will replay current track,
+        // so do not skip
+        TBool sendSkip( ETrue );
+        if ( iPlaylist )
+            {
+            if ( 0 != iPlaylist->Index() ||
+                 CMPXCollectionPlaylist::ERepeatOff != iPlaylist->RepeatMode() )
+                {
+                sendSkip = ETrue;
+                }
+            else
+                {
+                sendSkip = EFalse;
+                }
+            }
+        if ( sendSkip && EPlayFromCollection == iPlaySource && iPlaylist )
+            {
+            iClientList->SendMsgL(
+                TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipping, 0, -1 ));
+
+            if (iPlaylist->Count()>0)
+                {
+                iPlaylist->Previous( ETrue );
+                RequestMediaL();
+                }
+            }
+        }
+    else
+        {
+        iSkipping = EFalse;
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage( TMPXPlaybackMessage::ESkipEnd ));
+        }
+
+    MPX_DEBUG1("<==CMPXPlaybackEngine::HandleCmdBufferSkipEventL()");
+    }
+
+
+// ----------------------------------------------------------------------------
+// Suspend playback
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::Suspend()
+//
+// Should stop in current position, i.e. clearing timers etc.
+//
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::Suspend()");
+    iProgressTimer->Cancel();
+    EndSeek();
+    iAutoResumeHandler->CancelResumeTimer();
+    }
+
+// ----------------------------------------------------------------------------
+// Seek timer callback handler
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SeekTimerTick()
+    {
+    TInt& pos=iProperties[EPbPropertyPosition];
+    pos+=iSeekStep;
+    if (pos>iProperties[EPbPropertyDuration])
+        {
+        pos=iProperties[EPbPropertyDuration];
+        iSeekTimer->Cancel();
+        }
+    if (pos<0)
+        {
+        pos=0;
+        iSeekTimer->Cancel();
+        }
+
+    iSeekStep*=KPbSeekAccelerationFactor;
+    if (iSeekStep>iMaxSeekStep)
+        {
+        iSeekStep=iMaxSeekStep;
+        }
+    else if (iSeekStep<-iMaxSeekStep)
+        {
+        iSeekStep=-iMaxSeekStep;
+        }
+    TRAP_IGNORE(iClientList->SendMsgL(
+                    TMPXPlaybackMessage(TMPXPlaybackMessage::EPropertyChanged,
+                                        EPbPropertyPosition,
+                                        pos)));
+    }
+
+// ----------------------------------------------------------------------------
+// Seek timer callback
+// ----------------------------------------------------------------------------
+//
+TInt CMPXPlaybackEngine::SeekTimerCallback(TAny* aPtr)
+    {
+    static_cast<CMPXPlaybackEngine*>(aPtr)->SeekTimerTick();
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// Initialise helper method
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::InitL(const TDesC* aSong,
+                               const TDesC8* aType,
+                               RFile* aFile,
+                               TInt aAccessPoint)
+    {
+    MPX_DEBUG1("==>CMPXPlaybackEngine::InitL(const TDesC* aSong, const TDesC8* aType, RFile* aFile,TInt aAccessPoint)");
+    CMPXPlaybackPlugin* p( NULL );
+    if ( iPluginHandler->Plugin() )
+        {
+        TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose));
+        }
+    
+    if (aSong && aType)
+        {
+        MPX_DEBUG2("CMPXPlaybackEngine::InitL(%S)", aSong);
+        iPluginHandler->SelectPlayerL(*aSong,*aType);
+        }
+    else if (aFile)
+        {
+        iPluginHandler->SelectPlayerL(*aFile);
+        }
+    else
+        { // should never happen
+        ASSERT(0);
+        }
+
+    p=iPluginHandler->Plugin();
+    CheckPtrL(p);
+
+    if (p->Uid()!=iPluginUid)
+        { // new plugin or new playlist
+        iPluginUid = p->Uid();
+        iInitVolume = ETrue;
+        p->PropertyL( EPbPropertyVolume );
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerChanged));
+        }
+    // Stop and close opened file
+    TRAP_IGNORE(DoStopL(EFalse));
+    TRAP_IGNORE(p->CommandL(EPbCmdClose));
+
+    // If playing from a playlist, send the index as a data
+    // parameter.  This helps performance as the client
+    // doesn't need to request the index separately
+    TInt index( KErrNotFound );
+    if ( EPlayFromCollection == iPlaySource )
+        {
+        index = iPlaylist->Index();
+        }
+    
+    TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
+                             EPbStateInitialising,
+                             index );
+    SetStateL( msg );
+    iProperties[EPbPropertyPosition]=0;
+    
+    // make sure our interface is supported
+    CDesCArray* interfaces = iPluginHandler->SupportedInterfacesL( p->Uid() );
+    TBool version2InterfaceSupported = EFalse;
+    if (interfaces->MdcaCount())
+        {
+        TInt pos(0);            
+        version2InterfaceSupported = !interfaces->FindIsq(KMPXPlaybackPluginVersion2, pos);
+        }
+    delete interfaces;
+        
+    // cast the plugin to use our interface
+    if (version2InterfaceSupported)
+        {
+        CMPXPlaybackPluginVersion2* plugin = NULL;
+        plugin = static_cast<CMPXPlaybackPluginVersion2*>(p);
+        
+        // if cast was successful, then init streaming with access point
+        if (plugin)
+            {
+            if ( iAccessPointSet )
+                {
+                if (aSong && aType)
+                    {
+                    plugin->InitStreamingL( *aSong, *aType, aAccessPoint );
+                    }
+                else if (aFile)
+                    {
+                    plugin->InitStreamingL( *aFile, aAccessPoint );
+                    }
+                }
+            else
+                {
+                if (aSong && aType)
+                    {
+                    plugin->InitialiseL( *aSong );
+                    }
+                else if (aFile)
+                    {
+                    plugin->InitialiseL( *aFile );
+                    }        
+                }
+            }
+        else // if (plugin)
+            {
+            MPX_DEBUG1("CMPXPlaybackEngine::InitL(): *** Init Streaming failed -- failure to convert to expected interface");                
+            }
+        }
+    else // if (version2InterfaceSupported)
+        {
+        if (aSong && aType)
+            {
+            p->InitialiseL( *aSong );
+            }
+        else if (aFile)
+            {
+            p->InitialiseL( *aFile );
+            }        
+        }
+
+    MPX_DEBUG1("<==CMPXPlaybackEngine::InitL(const TDesC* aSong, const TDesC8* aType, RFile* aFile, TInt aAccessPoint)");
+    }
+
+// ----------------------------------------------------------------------------
+// Command handler
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCommandL(TMPXPlaybackCommand aCmd, TInt aData )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::HandleCommandL(%d) entering", aCmd);
+    switch(aCmd)
+        {
+        case EPbCmdPlay:
+            HandlePlayL();
+            break;
+        case EPbCmdStop:
+            HandleStopL();
+            break;
+        case EPbCmdPause:
+            HandlePauseL();
+            break;
+        case EPbCmdNext:
+            HandleNextL();
+            break;
+        case EPbCmdPrevious:
+            HandlePreviousL();
+            break;
+        case EPbCmdPlayWithFadeIn:
+            HandlePlayWithFadeInL();
+            break;
+        case EPbCmdStartSeekForward:
+            HandleStartSeekL(ETrue);
+            break;
+        case EPbCmdStartSeekBackward:
+            HandleStartSeekL(EFalse);
+            break;
+        case EPbCmdStopSeeking:
+            HandleStopSeekingL();
+            break;
+        case EPbCmdIncreaseVolume:
+            HandleIncreaseVolumeL();
+            break;
+        case EPbCmdDecreaseVolume:
+            HandleDecreaseVolumeL();
+            break;
+        case EPbCmdSetVolume:
+            HandleSetVolumeL( aData );
+            break;
+        case EPbCmdMuteVolume:
+            HandleMuteL(ETrue);
+            break;
+        case EPbCmdUnMuteVolume:
+            HandleMuteL(EFalse);
+            break;
+        case EPbCmdClose:
+            HandleCloseL( aData );
+            break;
+        case EPbCmdReplay:
+            HandleReplayL();
+            break;
+        case EPbApplyEffect:
+            HandleEffectL(aData);
+            break;
+		case EPbCmdDisableEffect:
+			HandleDisableEffectL();
+			break;
+        case EPbCmdPreservePosition:
+            iPreservedPosition = iProperties[EPbPropertyPosition];
+            break;
+        case EPbCmdPreserveState:
+            iPreservedState = iState;
+            break;
+        case EPbCmdCloseItem:
+            HandleCloseItemL( aData );
+            break;
+        case EPbCmdCancelInit:
+            {
+            if (EPbStateInitialising==iState)
+                {
+                PluginL()->CancelRequest();
+                iNextState = EPbStateStopped;
+
+                if (iPluginHandler->Plugin())
+                    {
+                    TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose, aData));
+                    }
+                if (iInitializer)
+                    {
+                    iInitializer->Close();
+                    }
+                //Needs to update iState and report the change to Ui
+                SetStateL(EPbStateStopped);
+                }
+            break;
+            }
+        case EPbCmdResetPreserveState:
+            {
+            iPreservedState = EPbStateNotInitialised;
+            break;
+            }
+        case EPbCmdUnloadNonActivePlugin:
+            {
+            TUid uid = TUid::Uid(aData);
+            if (iPluginHandler->Plugin())
+                {
+                if (iPluginHandler->Plugin()->Uid() != uid)
+                    { //not current active plugin
+                    iPluginHandler->UnloadPlugin(uid);
+                    }
+                }
+            if (iInitializer)
+                {
+                if (iInitializer->PluginUid() == uid)
+                    { //Plugin loaded in pre-initializer, not active one.
+                    iInitializer->Close();
+                    }
+                }
+            break;
+            }
+        case EPbCmdClearKeyBuffer:
+            {
+            MPX_DEBUG1("CMPXPlaybackEngine::HandleCommandL - EPbCmdClearKeyBuffer");
+            iCmdBuffer->ClearCommands();
+            break;
+            }
+        case EPbCmdSetAutoResume:
+            {
+            iAutoResumeHandler->SetAutoResume( aData );
+            break;
+            }
+        default:
+            ASSERT(0);
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleCommandL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle media properties from collection
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCollectionMediaL(
+    const CMPXMedia& aMedia,
+    TInt aError)
+    {
+    MPX_DEBUG3("-->CMPXPlaybackEngine::HandleCollectionMediaL 0x%08x err(%d)",
+               this, aError);
+
+    if (KErrNone == aError)
+        {
+        HBufC8* mimeType =
+                   MPXUser::Alloc8L(aMedia.ValueText(KMPXMediaGeneralMimeType));
+        CleanupStack::PushL(mimeType);
+
+        if(iUri)
+            {
+            delete iUri;
+            iUri = NULL;
+            }
+
+        iUri = aMedia.ValueText(KMPXMediaGeneralUri).AllocL();
+        MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL uri %S", iUri);
+
+        iItemId = KMPXInvalidItemId;
+        if (aMedia.IsSupported(KMPXMediaGeneralId))
+            {
+            iItemId = aMedia.ValueTObjectL<TMPXItemId>( KMPXMediaGeneralId );
+            MPX_DEBUG3("CMPXPlaybackEngine::HandleCollectionMediaL iItemId %d %d", iItemId.iId1, iItemId.iId2);
+            }
+
+        iDbFlag = 0;
+        if ( aMedia.IsSupported( KMPXMediaGeneralFlags ))
+            {
+            iDbFlag = aMedia.ValueTObjectL<TUint>( KMPXMediaGeneralFlags );
+            MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iDbFlag %x", iDbFlag);
+            }
+
+        iMediaDuration = 0;
+        if ( aMedia.IsSupported( KMPXMediaGeneralDuration ))
+            {
+            iMediaDuration = aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralDuration );
+            MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iMediaDuration %d", iMediaDuration);
+            }
+
+        iAccessPoint = 0;
+        iAccessPointSet = EFalse;
+        if ( aMedia.IsSupported(KMPXMediaGeneralExtAccessPoint) )
+            {
+            iAccessPoint = aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralExtAccessPoint );
+            MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL iAccessPoint %d", iAccessPoint );
+            iAccessPointSet = ETrue;
+            }
+        if (*iUri == KNullDesC)
+            {
+            aError = KErrNotFound;
+            }
+        else
+            {
+            TRAP( aError, InitL( iUri, mimeType, NULL, iAccessPoint) );
+            /*
+            // 20 steps  fix
+            // check whether we are playing WMA files, if so 
+            // the increment has to be KMPXLargeVolumeIncrement 
+		        TParsePtrC parser(*iUri);
+		            
+		        MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL(): iUri is %S", iUri);
+		        if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0)
+		            {
+		            // for wma file, the increment is always 10 with or without headset
+		            iVolumeIncrement = KMPXLargeVolumeIncrement;	
+		            MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionMediaL it is a wma/ra file, volumeIncrement: %d !!!!", iVolumeIncrement);	
+		            }
+#if defined(__HIGH_RESOLUTION_VOLUME)
+#ifdef __ACCESSORY_FW
+		        else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryWiredHeadset || iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadphones)
+#else        
+            else if (iAccessoryObs->AccessoryModeL() == EPbAccessoryHeadset)
+#endif // __ACCESSORY_FW
+		            {
+		            // for non wma files with headset, the volume increment is 5
+		            iVolumeIncrement = KMPXSmallVolumeIncrement;
+		            }
+#endif // HIGH_RESOLUTION_VOLUME    
+               */
+            if ( KErrNone == aError )
+                {
+                RestorePlaybackPositionAndStateL( aMedia );
+                }
+            else
+                {
+                iClientList->SendMsgL(TMPXPlaybackMessage(
+                        TMPXPlaybackMessage::EMediaChanged));
+                iState = EPbStateStopped;
+                }
+            }
+        CleanupStack::PopAndDestroy(mimeType);
+        }
+    else
+        {
+        // it'll be incorrect to leave iItemId unchanged, also KMPXInvalidItemId has special handling in
+        // CreateMediaToSetLC so we'd rather set Id to some actual value even if it had some 'issues'
+        iItemId = iPlaylist->Path().Id();
+        }
+
+    // Check for error again, just in case above code had any errors
+    if ( KErrNone != aError )
+        {
+        if ( KErrNotFound == aError ||
+             KErrPathNotFound == aError ||
+             KErrPermissionDenied == aError )
+            {
+            // Mark item as Invalid
+            MarkItemInvalid( ETrue );
+            iClientList->SendMsgL(
+               TMPXPlaybackMessage( TMPXPlaybackMessage::EError,
+                                    EPInitialised,
+                                    aError ));
+            }
+        else
+            { // other system error
+            HandleStopL();
+            }
+        }
+    MPX_DEBUG1("<--CMPXPlaybackEngine::HandleCollectionMediaL()");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle playlist change event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCollectionPlaylistChange(TInt aError)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandleCollectionPlaylistChange");
+    MPX_DEBUG2("CMPXPlaybackEngine::HandleCollectionPlaylistChange(%d)", aError);
+
+    if (KErrNotFound == aError)
+        {
+        if ( iPlaylist )
+            {
+            TRAP_IGNORE(HandleStopL());
+
+            // If playlist is empty now, update state
+            if ( iPlaylist->Count() == 0 )
+                {
+                iNextState = EPbStateNotInitialised;
+                iState = EPbStateNotInitialised;
+                }
+            }
+        }
+    else if(KErrEof == aError)
+        { // current item removed at the end
+        TRAP_IGNORE(HandleStopL());
+
+        // If playlist is empty now, update state
+        if ( iPlaylist->Count() == 0 )
+            {
+            iNextState = EPbStateNotInitialised;
+            iState = EPbStateNotInitialised;
+            }
+        else
+            {
+            TRAP_IGNORE(HandleNextL(1, ETrue));
+            }
+        }
+    else if (iInitializer)
+        { // Reset initializer anyway. Make sure it is synced
+         //iInitializer->Close();      //correct auto playlist crash
+        }
+    //update now playing view
+    TRAP_IGNORE(iClientList->SendMsgL(TMPXPlaybackMessage(
+                                TMPXPlaybackMessage::EPlaylistUpdated)));
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPlaybackEngine::HandlePluginHandlerEvent
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePluginHandlerEvent(
+    TPluginHandlerEvents aEvent,
+    const TUid& aPluginUid,
+    TBool aLoaded,
+    TInt aData)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandlePluginHandlerEvent");
+
+    switch (aEvent)
+        {
+        case MMPXPluginHandlerObserver::EPluginAdd:
+            {
+            TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginAdd, aPluginUid,
+                EFalse, aData));
+            break;
+            }
+        case MMPXPluginHandlerObserver::EPluginUpdateStart:
+            {
+            // Handling the unloading of the previous plugin version and the loading
+            // of the new plugin version is synchronous and therefore new requests
+            // will not be processed by the server/engine in between EPluginUpdateStart
+            // and EPluginUpdateEnd.
+            //
+            // If the plugin handler would unload/load plugins asynchronously then a
+            // mechanism must be created where new requests are not accepted for
+            // the plugin that is being updated for the duration of the update.
+
+            TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginUpdateStart,
+                aPluginUid, aLoaded, aData));
+
+            // If the current loaded plugin is being updated
+            if (iPluginHandler->Plugin() &&
+                (iPluginHandler->Plugin()->Uid() == aPluginUid))
+                {
+                // Complete all outstanding requests
+                iTaskQueue->CompleteAllTasks(KErrNotReady);
+                }
+            break;
+            }
+        case MMPXPluginHandlerObserver::EPluginUpdateEnd:
+            {
+            TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginUpdateEnd,
+                aPluginUid, aLoaded, aData));
+            break;
+            }
+        case MMPXPluginHandlerObserver::EPluginRemove:
+            {
+            // If the current loaded plugin is being removed
+            if (iPluginHandler->Plugin() &&
+                (iPluginHandler->Plugin()->Uid() == aPluginUid))
+                {
+                // Complete all outstanding requests
+                iTaskQueue->CompleteAllTasks(KErrNotReady);
+                }
+
+            TRAP_IGNORE(SendPluginHandlerMessageL(KMPXMessagePluginRemove,
+                aPluginUid, aLoaded));
+            break;
+            }
+
+        default:
+            {
+            // ignore the event
+            break;
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CMPXPlaybackEngine::SendPluginHandlerMessageL
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SendPluginHandlerMessageL(
+    TInt aMessageId,
+    const TUid& aPluginUid,
+    TBool aLoaded,
+    TInt aVersion /* = 0 */)
+    {
+    CMPXMessage* msg = CMPXMedia::NewL();
+    CleanupStack::PushL(msg);
+
+    msg->SetTObjectValueL<TMPXMessageId>(KMPXMessageGeneralId, aMessageId);
+    msg->SetTObjectValueL<TUid>(KMPXAttrPluginId, aPluginUid);
+    msg->SetTObjectValueL<TBool>(KMPXAttrPluginLoaded, aLoaded);
+    if (aVersion > 0)
+        {
+        msg->SetTObjectValueL<TInt>(KMPXAttrPluginVersion, aVersion);
+        }
+
+    iClientList->SendMsg(msg, KErrNone);
+
+    CleanupStack::PopAndDestroy(msg);
+    }
+
+// ----------------------------------------------------------------------------
+// Handle play command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePlayL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayL(): entering");
+    CMPXPlaybackPlugin* p(NULL);
+    TMPXPlaybackState oldNextState( iNextState );
+    iNextState = EPbStatePlaying;
+    if (EPbStateNotInitialised == iPluginState &&
+        EPlayFromCollection == iPlaySource &&
+        EPbStatePaused != iState)
+        {
+        MediaFromCollectionL();
+        }
+    else
+        {
+        switch (iState)
+            {
+            case EPbStatePlaying: //already playing, send message to update clients
+                if (EPbStatePaused == iPluginState)
+                    { // paused due to skipping
+                    PluginL()->CommandL(EPbCmdPlay);
+                    }
+                iClientList->SendMsgL(
+                    TMPXPlaybackMessage(
+                        TMPXPlaybackMessage::EStateChanged, iState));
+                break;
+            case EPbStateNotInitialised:    // No song initialised in engine
+                iNextState = EPbStateNotInitialised;
+                break;
+            case EPbStateSeekingForward:
+            case EPbStateSeekingBackward:
+                EndSeek();
+                p = PluginL();
+                p->CommandL(EPbCmdPlay);
+                break;
+            case EPbStatePaused:
+            case EPbStateStopped:
+                {
+                // If playing from collection playlist and currently in
+                // stopped state, then re-get media attributes
+                if ( EPlayFromCollection == iPlaySource &&
+                     EPbStateStopped == oldNextState )
+                    {
+                    MediaFromCollectionL();
+                    break;
+                    }
+                else if ( EPlayFromUri == iPlaySource &&
+                        EPbStateStopped == oldNextState )
+                    {
+                    TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ) );                    
+                    break;
+                    }
+                else
+                    {
+                    // fall through on purpose
+                    }
+                }
+            default:
+                {
+                p= PluginL();
+                p->CommandL(EPbCmdPlay);
+                break;
+                }
+            }
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle play command with fade in
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePlayWithFadeInL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayWithFadeInL(): entering");
+    MPX_DEBUG2("CMPXPlaybackEngine::HandlePlayWithFadeInL(): Ramp = %d", iProperties[EPbPropertyVolumeRamp]);
+    MPX_DEBUG2("CMPXPlaybackEngine::HandlePlayWithFadeInL(): Position = %d", iProperties[EPbPropertyPosition]);
+
+    CMPXPlaybackPlugin* p( PluginL() );
+    TRAP_IGNORE( // uPnP leaves if set in stop state
+        p->SetL( EPbPropertyVolumeRamp,
+                 iProperties[EPbPropertyVolumeRamp] ));
+    p->CommandL(EPbCmdPlay);
+    iNextState = EPbStatePlaying;
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePlayWithFadeInL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle pause command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePauseL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePauseL(): entering");
+    Suspend();
+    if ( EPbStatePaused == iState )
+        {
+        //already paused, send message to update clients
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(
+                TMPXPlaybackMessage::EStateChanged, iState));
+        }
+    else
+        {
+        if (EPbStatePlaying == iNextState)
+            { // only change state from playing to pause
+            iNextState = EPbStatePaused;
+            }
+        PluginL()->CommandL(EPbCmdPause);
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePauseL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle stop command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleStopL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStopL(): entering");
+    iNextState = EPbStateStopped;
+    TRAP_IGNORE(DoStopL());
+    if (iInitializer)
+        {
+        iInitializer->Close();
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStopL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Stop playback
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::DoStopL(TBool aSavePlaybackInfo)
+    {
+    MPX_DEBUG1("==>CMPXPlaybackEngine::DoStopL()");
+    Suspend();
+    if (iState == EPbStatePaused || iState == EPbStatePlaying ||
+        iState == EPbStateInitialising)
+        {
+        if (aSavePlaybackInfo && (iState == EPbStatePaused || iState == EPbStatePlaying ))
+            {
+            TRAP_IGNORE(SavePlaybackInfoL()); // Leave when MMC eject and database already closed.
+            }
+        PluginL()->CommandL(EPbCmdStop); // Leave if router power down
+        }
+    MPX_DEBUG1("<==CMPXPlaybackEngine::DoStopL()");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle next track command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleNextL(
+    TInt aOffset /*= 1*/,
+    TBool aIgnoreRepeat /*=EFalse*/ )
+    {
+    MPX_ASSERT(aOffset>0);
+    MPX_DEBUG2("CMPXPlaybackEngine::HandleNextL(%d) entering", aOffset);
+    EndSeek();
+    TBool next = ETrue;
+    TBool notify( ETrue );
+    if (EPlayFromCollection == iPlaySource && iPlaylist)
+        {
+        // Ignore command if playlist empty
+        if ( iPlaylist->Count() <= 0 )
+            {
+            next = EFalse;
+            notify = EFalse;
+            }
+        else
+            {
+            while (aOffset-->0)
+                {
+                if (!iPlaylist->Next( aIgnoreRepeat ))
+                    {
+                    iClientList->SendMsgL(
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::
+                                            EReachedEndOfPlaylist));
+                    iNextState = EPbStateStopped;
+                    if (iPlaylist->IsSingleItemPlaylist())
+                        {
+                        next = EFalse;
+                        }
+                    break;
+                    }
+                }
+            }
+        }
+
+    // Check if repeat mode is on and playing from a file or URI
+    else if ( iProperties[EPbPropertyRepeatMode] != EPbRepeatOff )
+        {
+        if ( EPlayFromFile == iPlaySource )
+            {
+            TRAP_IGNORE( InitL( NULL, NULL, &iFile, iAccessPoint ));            
+            }
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+        else if ( EPlayFromFile64 == iPlaySource )
+            {
+            TRAP_IGNORE( Init64L( &iFile64, iAccessPoint ));            
+            }
+#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+        else if ( EPlayFromUri == iPlaySource )
+            {
+            TRAP_IGNORE( InitL( iUri, &( KNullDesC8 ), NULL, iAccessPoint ));            
+            }
+        else
+            {
+            HandleStopL();
+            }
+        next = EFalse;
+        }
+    else
+        {
+        HandleStopL();
+        next = EFalse;
+        }
+    
+    if (next)
+        {
+        // query collection for next song
+        MediaFromCollectionL();
+        }
+    else if ( notify )
+        { // trigger UI to update duration
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleNextL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle previous command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandlePreviousL(
+    TInt aOffset /*= -1*/,
+    TBool aIgnoreRepeat /*=EFalse*/ )
+    {
+    MPX_ASSERT(aOffset<0);
+    MPX_DEBUG2("CMPXPlaybackEngine::HandlePreviousL(%d) entering", aOffset);
+    EndSeek();
+    if (EPlayFromCollection == iPlaySource && iPlaylist)
+        {
+        // Ignore command if playlist empty
+        if ( iPlaylist->Count() > 0 )
+            {
+            // If first item in list and repeat is off, then replay the song
+            if ( 0 == iPlaylist->Index() &&
+                 CMPXCollectionPlaylist::ERepeatOff == iPlaylist->RepeatMode() )
+                {
+                if ( EPbStatePlaying == iState ||
+                     EPbStatePaused == iState )
+                    {
+                    HandleReplayL();
+                    }
+                }
+            else
+                {
+                aOffset = -aOffset;
+                while (aOffset-->0)
+                    {
+                    if (!iPlaylist->Previous( aIgnoreRepeat ))
+                        {
+                        HandleStopL();
+                        break;
+                        }
+                    }
+                MediaFromCollectionL();
+                }
+            }
+        }
+    else
+        {
+        HandleStopL();
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandlePreviousL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle replay command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleReplayL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL(): entering");
+    EndSeek();
+    iProperties[EPbPropertyPosition] = 0;
+    if ( PluginL() )
+        {
+        TMPXPlaybackState prevState( iState );
+        if ( iState == EPbStatePlaying )
+            {
+            // Need to send pause command to plugin first so that it will
+            // not keep playing the rest of it's buffer
+            MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL() send pause command");
+            iState = EPbStatePaused;
+            PluginL()->CommandL(EPbCmdPause);
+            }
+        PluginL()->SetL(EPbPropertyPosition,
+                        iProperties[EPbPropertyPosition]);
+        if ( prevState == EPbStatePlaying )
+            {
+            PluginL()->CommandL(EPbCmdPlay);
+            }
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleReplayL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle start seeking command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleStartSeekL(TBool aForward)
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStartSeekL(): entering");
+    if (iState==EPbStatePlaying ||
+        iState==EPbStatePaused ||
+        iState==EPbStateSeekingForward ||
+        iState==EPbStateSeekingBackward)
+        {
+        Suspend();
+        if (iState != EPbStateSeekingForward &&
+            iState != EPbStateSeekingBackward)
+            {
+            iNextState = iState;
+            }
+
+        SetStateL(aForward?EPbStateSeekingForward:EPbStateSeekingBackward);
+
+        PluginL()->CommandL(EPbCmdPause);
+
+        TCallBack cb(SeekTimerCallback,this);
+        iSeekStep = aForward ? KPbInitialSeekStepMilliSeconds :
+                               -KPbInitialSeekStepMilliSeconds;
+        if ( iSeekTimer->IsActive() )
+            iSeekTimer->Cancel();
+        iSeekTimer->Start(KPbSeekIntervalMicroSeconds,
+                          KPbSeekIntervalMicroSeconds, cb);
+        MPX_DEBUG2("CMPXPlaybackEngine sends msg EStateChanged to %d", iState);
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStartSeekL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle stop seeking command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleStopSeekingL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStopSeekingL(): entering");
+
+    // Only perform actions if we are currently in seeking state
+    if (iState == EPbStateSeekingForward ||
+        iState == EPbStateSeekingBackward)
+        {
+        EndSeek();
+        if (EPbStateNotInitialised == iPluginState &&
+            EPlayFromCollection == iPlaySource )
+            {
+            iPreservedPosition = iProperties[EPbPropertyPosition];
+            MediaFromCollectionL();
+            }
+        else
+            {
+            PluginL()->SetL(EPbPropertyPosition,iProperties[EPbPropertyPosition]);
+            iState = iNextState;
+            switch ( iState )
+                {
+                case EPbStatePlaying:
+                    {
+                    iClientList->SendMsgL( // update UI icons
+                       TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+                    PluginL()->CommandL( EPbCmdPlay );
+                    break;
+                    }
+                case EPbStatePaused:
+                    {
+                    iClientList->SendMsgL( // update UI icons
+                        TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged,iState));
+                    break;
+                    }
+                default:
+                    break;
+                }
+            }
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleStopSeekingL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle increase volume command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleIncreaseVolumeL()
+    {
+    TInt level( iProperties[EPbPropertyVolume] );   	
+#if defined(__HIGH_RESOLUTION_VOLUME)
+    // if we already rounded up last time, don't have to increase,
+    // reset flag
+    if (!iVolRoundedUp)
+        {
+        level += iVolumeIncrement;
+        }
+#else    	
+    level += iVolumeIncrement;
+#endif
+    // Ensure that level is within min and max values
+    if (level > KPbPlaybackVolumeLevelMax)
+        {
+        level = KPbPlaybackVolumeLevelMax;
+        }
+    if (level < KPbPlaybackVolumeLevelMin)
+        {
+        level = KPbPlaybackVolumeLevelMin;
+        }
+
+    SetL(EPbPropertyVolume, level);
+    }
+
+// ----------------------------------------------------------------------------
+// Handle decrease volume command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleDecreaseVolumeL()
+    {
+    TInt level( iProperties[EPbPropertyVolume] - iVolumeIncrement );
+
+    // Ensure that level is within min and max values
+    if (level > KPbPlaybackVolumeLevelMax)
+        {
+        level = KPbPlaybackVolumeLevelMax;
+        }
+    if (level < KPbPlaybackVolumeLevelMin)
+        {
+        level = KPbPlaybackVolumeLevelMin;
+        }
+
+    SetL(EPbPropertyVolume, level);
+    }
+
+// ----------------------------------------------------------------------------
+//  Handle set volume command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleSetVolumeL(TInt aVolume)
+    {
+    TInt level = aVolume;
+
+    // Ensure that level is within min and max values
+    if (level > KPbPlaybackVolumeLevelMax)
+        {
+        level = KPbPlaybackVolumeLevelMax;
+        }
+    if (level < KPbPlaybackVolumeLevelMin)
+        {
+        level = KPbPlaybackVolumeLevelMin;
+        }
+
+    SetL(EPbPropertyVolume, level);
+    }
+
+// ----------------------------------------------------------------------------
+// Handle mute command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleMuteL(TBool aMute)
+    {
+    SetL(EPbPropertyMute, aMute);
+    }
+
+// ----------------------------------------------------------------------------
+// Handle close command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCloseL( TInt aData )
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleCloseL(): entering");
+    if (iPluginHandler->Plugin())
+        {
+        TRAP_IGNORE(DoStopL());
+        iNextState = EPbStateNotInitialised;
+        TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose, aData));
+        DoClose();
+        }
+    if (iInitializer)
+        {
+        iInitializer->Close();
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::HandleCloseL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle a custom command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleEffectL(TInt aData)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandleEffectL()");
+    if(iPluginHandler->Plugin())
+        {
+        iPluginHandler->Plugin()->CommandL(EPbApplyEffect, aData);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Handle a custom command
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleDisableEffectL()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandleDisableEffectL()");
+    if(iPluginHandler->Plugin())
+        {
+        iPluginHandler->Plugin()->CommandL(EPbCmdDisableEffect);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Handle request to close a specific item
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleCloseItemL( TInt aItemId )
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::HandleCloseItemL()");
+
+    if( iPlaylist )
+        {
+        // If the item is currently in play, close playback or
+        // if item is currently in the initializer
+        if( iPlaylist->Path().Id().ApproxEqual( aItemId  ) )
+            {
+            HandleStopL();
+            }
+        else if(iInitializer)
+            {
+            TInt nextIndex;
+            TBool repeatMode;
+            repeatMode = iPlaylist->RepeatMode();
+            TBool nextFound = iPlaylist->NextIndex( repeatMode, nextIndex );
+            TMPXItemId nextItemId = iPlaylist->Path().IdOfIndex( nextIndex );
+            
+            if((iInitializer->CurrentInitItemId().iId2 == aItemId) || 
+                ( iInitNext && nextFound && nextItemId.ApproxEqual( aItemId )))
+                {
+                iInitializer->Close();
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Sets the plug-in properties
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetPropertiesL()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::SetPropertiesL()");
+    iMaxSeekStep = iProperties[EPbPropertyDuration]/KPercentMultiplier*KPbMaxSeekStepPercent;
+    MPX_DEBUG2("CMPXPlaybackEngine::SetPropertiesL(): iMediaDuration                   = %d", iMediaDuration);
+    MPX_DEBUG2("CMPXPlaybackEngine::SetPropertiesL(): iProperties[EPbPropertyDuration] = %d", iProperties[EPbPropertyDuration]);
+    if ( Abs(iMediaDuration - iProperties[EPbPropertyDuration]) >
+         KPbDurationChangeThreshold )
+        {
+        MPX_DEBUG1("CMPXPlaybackEngine::SetPropertiesL(): Duration not equal");
+        // Set duration if it's different than what collection has
+        if ( iPlaylist)
+            {
+            if ( iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist() )
+                {
+                MPX_DEBUG1("CMPXPlaybackEngine::SetPropertiesL(): Setting duration");
+                CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
+
+                iMediaDuration = iProperties[EPbPropertyDuration];
+                media->SetTObjectValueL( KMPXMediaGeneralDuration,
+                                         iProperties[EPbPropertyDuration] );
+                iPlaylist->SetL( *media );
+                CleanupStack::PopAndDestroy( media );
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Stop seeking timer
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::EndSeek()
+    {
+    if (iSeekTimer)
+        {
+        iSeekTimer->Cancel();
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Set playback state
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetStateL(TMPXPlaybackState aState)
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::SetStateL(%d): entering", aState);
+
+    TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
+                             aState );
+    SetStateL( msg );
+    MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Set playback state
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetStateL( TMPXPlaybackMessage& aMsg )
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(aMsg): entering");
+
+    TMPXPlaybackState state( static_cast<TMPXPlaybackState>( aMsg.Type() ));
+    MPX_DEBUG2("CMPXPlaybackEngine::SetStateL(): state = %d", state);
+
+    if ( state!=iState )
+        {
+        iState = state;
+        iAutoResumeHandler->HandlePlaybackStateChange( iState );
+        MPX_DEBUG2("CMPXPlaybackEngine sends msg EStateChanged to %d", iState);
+        iClientList->SendMsgL( aMsg );
+        }
+    // Restart progress timer
+    if (EPbStatePlaying == iState && !iProgressTimer->IsActive())
+        {
+        iProgressTimer->Start(ETwelveOClock,this);
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::SetStateL(aMsg): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Set player activated
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetPlayerActivated(TBool aActive)
+    {
+    MPX_DEBUG3("CMPXPlaybackEngine::SetPlayerActivated old = %d, new = %d",
+                iPlayerActive, aActive);
+    if (iPlayerActive != aActive)
+        {
+        iPlayerActive = aActive;
+        // triggle clients to update playback state
+        TRAP_IGNORE(iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EStateChanged, iState)));
+        MPX_DEBUG1("Playback Engine notify server active player chnaged.");
+        TRAP_IGNORE(iObserver.HandleActiveEngineL(this, iPlayerActive));
+        }
+    MPX_DEBUG1("CMPXPlaybackEngine::SetPlayerActivated(): exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Execute a async task
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::ExecuteTask(
+    TInt aTask,
+    TInt aParamData,
+    TAny* aPtrData,
+    const CBufBase& aBuf,
+    TAny* aCallback,
+    CBase* aCObject1,
+    CBase* aCObject2)
+    {
+    TRAPD(err, ExecuteTaskL(aTask, aParamData, aPtrData,
+                            aCallback, aBuf, aCObject1, aCObject2));
+    if (KErrNone != err)
+        {
+        HandleError(aTask, err, aParamData);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Indicates that a task was terminated with an error.
+// This will be called in case of a plugin update/removal.
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleTaskError(
+    TInt aTask,
+    TAny* /*aPtrData*/,
+    TAny* /*aCallback*/,
+    TInt aError)
+    {
+    MPX_FUNC("CMPXCollectionClientContext::HandleTaskError");
+    HandleError(aTask, aError);
+    }
+
+// ----------------------------------------------------------------------------
+// Execute a async task
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::ExecuteTaskL(
+    TInt aTask,
+    TInt aParamData,
+    TAny* aPtrData,
+    TAny* aCallback,
+    const CBufBase& /*aBuf*/,
+    CBase* aCObject1,
+    CBase* /*aCObject2*/)
+    {
+    MPX_DEBUG5("-->CMPXPlaybackEngine::ExecuteTaskL 0x%08x cb 0x%08x (%d, %d)",
+                this, aCallback, aTask, aParamData);
+    if ( aTask != EHandleNext )
+        {
+        ASSERT(aCallback);
+        iCallback = static_cast<MMPXPlaybackEngineObserver*>(aCallback);
+        }
+    CMPXPlaybackPlugin* p = aPtrData ?
+                            static_cast<CMPXPlaybackPlugin*>(aPtrData) :
+                            iPluginHandler->Plugin();
+    switch(aTask)
+        {
+        case EProperty:
+            {
+            CheckPtrL(p);
+            p->PropertyL(static_cast<TMPXPlaybackProperty>(aParamData));
+            break;
+            }
+        case EMedia:
+            {
+            iMediaAttrs.Reset();
+            CMPXCommand* cmd( static_cast<CMPXAttributeSpecs*>(aCObject1));
+            const TDesC& attr = cmd->ValueText( KMPXCommandMediaAttribute );
+            TPtrC8 ptr = MPXUser::Ptr( attr );
+            RDesReadStream readStream( ptr );
+            CleanupClosePushL( readStream );
+            // Internalize attributes
+            ::InternalizeL( iMediaAttrs, readStream );
+            CleanupStack::PopAndDestroy( &readStream );
+            CheckPtrL( p );
+            TMPXPlaybackState state(State());
+            if (( EPbStateInitialising == state ||
+                  EPbStatePlaying == state ||
+                  EPbStatePaused == state ||
+                  EPbStateStopped == state ||
+                  EPbStateBuffering == state ||
+                  EPbStateDownloading == state ||
+                  EPbStateInitialised == state ))
+                {
+                CMPXAttributeSpecs* specs( NULL );
+                if ( cmd->IsSupported( KMPXCommandMediaAttributeSpecs ) )
+                    {
+                    specs = cmd->Value<CMPXAttributeSpecs>( KMPXCommandMediaAttributeSpecs );
+                    User::LeaveIfNull(specs);
+                    }
+                p->MediaL( iMediaAttrs.Array(), specs );
+                }
+            else
+                {
+                CMPXMedia *media = CMPXMedia::NewL();
+                CleanupStack::PushL(media);
+                media->SetTObjectValueL(KMPXMediaColDetailMediaNotAvailable,
+                                        ETrue);
+                HandleMedia(media, KErrNone);
+                CleanupStack::PopAndDestroy(media);
+                }
+            }
+            break;
+        case ESubPlayerNames:
+            {
+            CheckPtrL(p);
+            p->SubPlayerNamesL();
+            break;
+            }
+        case EHandleNext:
+            {
+            HandleNextL();
+			if( iPlaylist )
+			    {
+                iClientList->SendMsgL(TMPXPlaybackMessage(
+                            TMPXPlaybackMessage::EMediaChanged));
+			    }
+            SetStateL( iState );
+            iTaskQueue->CompleteTask();
+            break;
+            }
+        default:
+            ASSERT(0);
+        }
+    MPX_DEBUG4("<--CMPXPlaybackEngine::ExecuteTaskL 0x%08x (%d, %d): Exiting",
+                this, aTask, aParamData);
+    }
+
+// ----------------------------------------------------------------------------
+// Error happens upon request
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::HandleError(
+    TInt aTask,
+    TInt aError,
+    TInt aParamData /* = 0 */)
+    {
+    MPX_DEBUG3("-->CMPXPlaybackEngine::HandleError() 0x%08x: aError %d", this, aError);
+    switch (aTask)
+        {
+        case EProperty:
+            iCallback->HandleProperty(
+                   static_cast<TMPXPlaybackProperty>(aParamData),
+                   0,aError);
+            iCallback = NULL;
+            break;
+        case EMedia:
+            {
+            iCallback->HandleMedia(NULL, aError);
+            iCallback = NULL;
+            }
+            break;
+        case ESubPlayerNames:
+            {
+            TUid piid=TUid::Uid(aParamData);
+            iCallback->HandleSubPlayerNames(piid, NULL, ETrue, aError);
+            iCallback = NULL;
+            }
+            break;
+        default:
+            ASSERT(0);
+            break;
+        }
+    iTaskQueue->CompleteTask();
+    MPX_DEBUG3("<--CMPXPlaybackEngine::HandleError() 0x%08x: aError %d", this, aError);
+    }
+
+// ----------------------------------------------------------------------------
+// Get command from state
+// ----------------------------------------------------------------------------
+//
+TMPXPlaybackCommand CMPXPlaybackEngine::CommandFromState(
+    TMPXPlaybackState aState )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::CommandFromState(): aState %d", aState);
+    TMPXPlaybackCommand cmd(EPbCmdStop);
+    switch ( aState )
+        {
+        case EPbStatePlaying:
+            cmd = EPbCmdPlay;
+            break;
+        case EPbStatePaused:
+            cmd = EPbCmdPause;
+            break;
+        case EPbStateStopped:
+            cmd = EPbCmdStop;
+            break;
+        default:
+            break;
+        }
+    return cmd;
+    }
+
+// ----------------------------------------------------------------------------
+// Do close
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::DoClose()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::DoClose()");
+    if (iTaskQueue)
+        {
+        iTaskQueue->CancelRequests();
+        }
+
+    iAutoResumeHandler->CancelResumeTimer();
+
+    if (iProgressTimer)
+        {
+        iProgressTimer->Cancel();
+        }
+
+    if (iSeekTimer)
+        {
+        iSeekTimer->Cancel();
+        }
+
+    iCmdBuffer->ClearCommands();
+
+    iFile.Close();
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+    iFile64.Close();
+#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+    delete iPlaylist;
+    iPlaylist = NULL;
+    delete iUri;
+    iUri = NULL;
+    iItemId = KMPXInvalidItemId;
+    iPlaySource = EPlayNone;
+    iState = EPbStateNotInitialised;
+    iNextState = EPbStateNotInitialised;
+    }
+
+// ----------------------------------------------------------------------------
+// URI from collection
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::MediaFromCollectionL()
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::MediaFromCollectionL");
+    if (iInitNext)
+        {
+        iInitializer->Init(*iPlaylist);
+        iInitializer->SetActiveL();
+        }
+    else
+        {
+        RArray<TMPXAttribute> attrs;
+        CleanupClosePushL(attrs);
+        attrs.AppendL(KMPXMediaGeneralId);
+        attrs.AppendL(KMPXMediaGeneralUri);
+        attrs.AppendL(KMPXMediaGeneralMimeType);
+        attrs.AppendL(KMPXMediaGeneralLastPlaybackPosition);
+        attrs.AppendL(KMPXMediaGeneralFlags);
+
+        if (iPlaylist)	///in some cases this could be empty
+			{
+        	iPlaylist->MediaL(attrs.Array(),*this);
+			}
+
+        CleanupStack::PopAndDestroy(&attrs);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Save playback position
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SavePlaybackInfoL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackInfoL() entering");
+
+    if ( iPlaylist)
+        {
+        if (iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist())
+            {
+            CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
+
+            // Save position, if at the end, then save position is 0
+            // Due to timer callbacks, the current position may not be exactly
+            // at the same value as the duration, thus must give it a
+            // threshold to be within.
+            TInt savePosition( iProperties[EPbPropertyPosition] );
+            if ( Abs( iProperties[EPbPropertyDuration] - savePosition ) <
+                 KPbPositionChangeThreshold )
+                {
+                savePosition = 0;
+                }
+            media->SetTObjectValueL( KMPXMediaGeneralLastPlaybackPosition,
+                                    savePosition );
+            iPlaylist->SetL( *media );
+            CleanupStack::PopAndDestroy(media);
+            }
+        }
+
+    MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackInfoL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Increments play count
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SavePlaybackCompleteInfoL()
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackCompleteInfoL() entering");
+
+    if ( iPlaylist )
+        {
+        if ( iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist() )
+            {
+            CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
+
+            // Increment play count
+            // Collection implementation will increment count by the
+            // value provided
+            media->SetTObjectValueL( KMPXMediaGeneralPlayCount,
+                                     1 );
+
+            // reset the last playback position to 0
+            media->SetTObjectValueL( KMPXMediaGeneralLastPlaybackPosition,
+                                     0 );
+
+            // Set last play time
+            TTime now;
+            now.UniversalTime();
+            media->SetTObjectValueL(KMPXMediaGeneralLastPlaybackTime,
+                    now.Int64() );
+
+            iPlaylist->SetL( *media );
+            CleanupStack::PopAndDestroy( media );
+            }
+        }
+
+    MPX_DEBUG1("CMPXPlaybackEngine::SavePlaybackCompleteInfoL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Restore playback position if it was saved previously
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::RestorePlaybackPositionAndStateL(
+    const CMPXMedia& aMedia )
+    {
+    MPX_DEBUG1("CMPXPlaybackEngine::RestorePlaybackPositionAndStateL() entering");
+
+    // Restore Position
+    iProperties[EPbPropertyPosition] = 0;
+    if ( KErrNotFound != iPreservedPosition )
+        {
+        iProperties[EPbPropertyPosition] = iPreservedPosition;
+        iPreservedPosition = KErrNotFound;
+        }
+    else
+        {
+        // Check media
+        if (aMedia.IsSupported(KMPXMediaGeneralLastPlaybackPosition))
+            {
+            iProperties[EPbPropertyPosition] =
+                aMedia.ValueTObjectL<TInt>( KMPXMediaGeneralLastPlaybackPosition );
+            }
+        }
+
+    // Restore State
+    if ( EPbStateNotInitialised != iPreservedState )
+        {
+        iNextState = iPreservedState;
+        iPreservedState = EPbStateNotInitialised;
+        }
+
+    MPX_DEBUG1("CMPXPlaybackEngine::RestorePlaybackPositionAndStateL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Sets the volume increment depending on accessory state
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetVolumeIncrement( TMPXPlaybackAccessoryMode aMode )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(%d) entering", aMode);
+
+    switch ( aMode )
+        {
+#ifdef __ACCESSORY_FW
+        case EPbAccessoryWiredHeadset:
+        case EPbAccessoryHeadphones:
+#else
+        case EPbAccessoryHeadset:
+#endif // __ACCESSORY_FW
+            {
+// twentysteps  start
+            	
+            // check whether we are playing WMA files, if so the increment has to be KMPXLargeVolumeIncrement 
+                if(iUri)
+                {
+                //MPX_DEBUG1("still alive one !!!!");	
+		            TParsePtrC parser(*iUri);
+		            
+		            MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): iUri is %S", iUri);
+
+		            if (parser.Ext().CompareF(KWmaExtension) == 0 || parser.Ext().CompareF(KRaExtension) == 0 )
+		                {
+		                iVolumeIncrement = KMPXLargeVolumeIncrement;	
+		                }
+		            else
+		                {
+		                iVolumeIncrement = KMPXSmallVolumeIncrement;	
+		                }
+                }
+            else
+                {
+                MPX_DEBUG1("CMPXPlaybackEngine::SetVolumeIncrement iUri is NULL");  
+                iVolumeIncrement = KMPXSmallVolumeIncrement;	
+                }
+                         
+            MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): Headset is inserted, increment is %d", iVolumeIncrement);
+//  twentysteps  end            
+// uncomment this when twentysteps is removed            iVolumeIncrement = KMPXSmallVolumeIncrement;
+            break;
+            }
+        default:
+            {
+            // for everything else check what is the current volume value
+            // and if an not an interval of KMPXLargeVolumeIncrement,
+            //  which could be the case if the last
+            // time user listened to music and wired headset was plugged in,
+            // then convert the value used to an increment of KMPXLargeVolumeIncrement.
+            MPX_DEBUG2("CMPXPlaybackEngine::SetVolumeIncrement(): NOT a headset, increment is %d", KMPXLargeVolumeIncrement);
+            iVolumeIncrement = KMPXLargeVolumeIncrement;
+            if ( iProperties[EPbPropertyVolume] > KPbPlaybackVolumeLevelMin && 
+                 iProperties[EPbPropertyVolume] < KPbPlaybackVolumeLevelMax)
+                {    
+#if defined(__HIGH_RESOLUTION_VOLUME)
+                // if we will round up the volume to next increment of 10, set the flag
+                // so when the headset is unplugged, we just increment it again.        
+                if (iProperties[EPbPropertyVolume] % KMPXLargeVolumeIncrement)
+                    {
+                    iVolRoundedUp = ETrue;
+                    }
+#endif
+                while ( iProperties[EPbPropertyVolume] % KMPXLargeVolumeIncrement &&
+                        iProperties[EPbPropertyVolume] <= KPbPlaybackVolumeLevelMax )
+                    {
+                    // increase volume until it's a valid increment of KMPXLargeVolumeIncrement
+                    iProperties[EPbPropertyVolume]++;
+                    }
+                }
+            break;
+            }
+        }
+
+    MPX_DEBUG1("CMPXPlaybackEngine::SetVolumeIncrement() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Marks the current item as corrupted
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::MarkItemCorrupted( const TBool aCorrupted )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::MarkItemCorrupted(%d) entering", aCorrupted);
+
+    TRAP_IGNORE( SetFlagBitsL( aCorrupted, KMPXMediaGeneralFlagsIsCorrupted ));
+
+    MPX_DEBUG1("CMPXPlaybackEngine::MarkItemCorrupted() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Marks the current item as invalid
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::MarkItemInvalid( const TBool aInvalid )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::MarkItemInvalid(%d) entering", aInvalid);
+
+    TRAP_IGNORE( SetFlagBitsL( aInvalid, KMPXMediaGeneralFlagsIsInvalid ));
+
+    MPX_DEBUG1("CMPXPlaybackEngine::MarkItemInvalid() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Marks the current item as DRM invalid
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::MarkItemDrmInvalid( const TBool aDrmInvalid )
+    {
+    MPX_DEBUG2("CMPXPlaybackEngine::MarkItemDrmInvalid(%d) entering", aDrmInvalid);
+
+    TRAP_IGNORE( SetFlagBitsL( aDrmInvalid, KMPXMediaGeneralFlagsIsDrmLicenceInvalid ));
+
+    MPX_DEBUG1("CMPXPlaybackEngine::MarkItemDrmInvalid() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Sets flag bits
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::SetFlagBitsL(
+    const TBool aSet,
+    const TUint aFlag )
+    {
+    MPX_DEBUG3("CMPXPlaybackEngine::SetFlagBitsL(%d, %d) entering", aSet, aFlag);
+
+    if ( iPlaylist)
+        {
+        if (iPlaylist->Count() && !iPlaylist->EmbeddedPlaylist())
+            {
+            CMPXMedia* media( CreateMediaToSetLC( iPlaylist->Path() ));
+
+            // Set flag
+            TUint flag( 0 );
+            if ( aSet )
+                {
+                flag = KMPXMediaGeneralFlagsSetOrUnsetBit;
+                }
+            flag |= aFlag;
+            media->SetTObjectValueL( KMPXMediaGeneralFlags,
+                                     flag );
+            iPlaylist->SetL( *media );
+            CleanupStack::PopAndDestroy( media );
+            }
+        }
+
+    MPX_DEBUG1("CMPXPlaybackEngine::SetFlagBitsL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Creates a CMPXMedia object to be used to Set attributes
+// ----------------------------------------------------------------------------
+//
+CMPXMedia* CMPXPlaybackEngine::CreateMediaToSetLC( const CMPXCollectionPath& aPath )
+    {
+    MPX_DEBUG1("-->CMPXPlaybackEngine::CreateMediaToSetLC()");
+
+    // Create new Media object to set
+    CMPXMedia* media = CMPXMedia::NewL();
+    CleanupStack::PushL(media);
+    media->SetTObjectValueL( KMPXMediaGeneralType,
+                             EMPXItem );
+    media->SetTObjectValueL( KMPXMediaGeneralCategory,
+                             EMPXSong );
+    media->SetTObjectValueL( KMPXMediaGeneralCollectionId,
+                             aPath.Id( CMPXCollectionPath::ECollectionUid ));
+
+    if (iItemId != KMPXInvalidItemId)
+        {
+        media->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, iItemId);
+        }
+    else if (iUri)
+        {
+        media->SetTextValueL( KMPXMediaGeneralUri, *iUri);
+        }
+    else
+        {
+        media->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId , aPath.Id() );
+        }
+    MPX_DEBUG1("<--CMPXPlaybackEngine::CreateMediaToSetLC()");
+    return media;
+    }
+
+// ----------------------------------------------------------------------------
+// Sends a request to iMediaHelper to request media
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::RequestMediaL()
+    {
+    MPX_FUNC( "CMPXPlaybackEngine::RequestMediaL" );
+    CMPXCommand* cmd = CMPXCommand::NewL();
+    CleanupStack::PushL( cmd );
+    cmd->SetTObjectValueL<TInt>(KMPXCommandGeneralId, KMPXCommandContentIdMedia);
+    CBufBase* buf = CBufFlat::NewL( KMPXBufGranularity );
+    CleanupStack::PushL( buf );
+
+    // Setup array buffer
+    RArray<TMPXAttribute> attrs;
+    CleanupClosePushL( attrs );
+    attrs.AppendL( KMPXMediaGeneralBasic );
+    attrs.AppendL( KMPXMediaGeneralUri );
+    attrs.AppendL( KMPXMediaMusicAlbumArtFileName );
+    attrs.AppendL( KMPXMediaMusicArtist );
+    attrs.AppendL( KMPXMediaMusicAlbum );
+
+    RBufWriteStream writeStream( *buf );
+    CleanupClosePushL( writeStream );
+    // externalize attributes array
+    ::ExternalizeL(attrs.Array(), writeStream);
+    // Close and compress buffer
+    writeStream.CommitL();
+    buf->Compress();
+    CleanupStack::PopAndDestroy( &writeStream );
+    CleanupStack::PopAndDestroy( &attrs );
+    TPtrC ptr = MPXUser::Ptr( buf->Ptr( 0 ) );
+    cmd->SetTextValueL( KMPXCommandMediaAttribute, ptr );
+
+    CMPXAttributeSpecs* attrSpecs = CMPXAttributeSpecs::NewL();
+    CleanupStack::PushL(attrSpecs);
+    cmd->SetCObjectValueL<CMPXAttributeSpecs>(
+        KMPXCommandMediaAttributeSpecs, attrSpecs );
+    CleanupStack::PopAndDestroy(attrSpecs);
+
+    iMediaHelper->MediaL( iPlaylist->Path(), cmd, NULL, ETrue, iClientList );
+    CleanupStack::PopAndDestroy( buf );
+    // Onwership of media is passed to mediahelper class
+    CleanupStack::Pop( cmd );
+    }
+
+#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+// ----------------------------------------------------------------------------
+// Initialises from file.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::Init64L(const RFile64& aFile)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::Init64L(const RFile64& aFile)");
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromFile64;
+    iNextState=EPbStateNotInitialised;
+    iFile64.Duplicate(aFile);
+    TRAPD( err, Init64L(&iFile64) );
+    if ( KErrNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialises from file.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXPlaybackEngine::InitStreaming64L(const RFile64& aFile, const TInt aAccessPoint)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::InitStreaming64L(const RFile64& aFile, const TInt aAccessPoint)");
+    iPluginUid = KNullUid; // Reset plugin uid for current item
+    iInitNext=EFalse;
+    HandleCloseL();
+    iPlaySource=EPlayFromFile64;
+    iNextState=EPbStateNotInitialised;
+    iFile64.Duplicate(aFile);
+    iAccessPoint = aAccessPoint;
+    iAccessPointSet = ETrue;
+    TRAPD( err, Init64L(&iFile64,aAccessPoint));
+    if ( KErrNotFound == err )
+        {
+        // Mark item as Invalid
+        MarkItemInvalid( ETrue );
+        User::Leave( err );
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Initialise helper method
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaybackEngine::Init64L(RFile64* aFile, TInt aAccessPoint)
+    {
+    MPX_FUNC_EX("CMPXPlaybackEngine::Init64L(RFile64* aFile,TInt aAccessPoint)");
+    CMPXPlaybackPlugin* p( NULL );
+    if ( iPluginHandler->Plugin() )
+        {
+        TRAP_IGNORE(iPluginHandler->Plugin()->CommandL(EPbCmdClose));
+        }
+    
+    if (aFile)
+        {
+        iPluginHandler->SelectPlayer64L(*aFile);
+        }
+    else
+        { // should never happen
+        ASSERT(0);
+        }
+
+    p=iPluginHandler->Plugin();
+    CheckPtrL(p);
+
+    if (p->Uid()!=iPluginUid)
+        { // new plugin or new playlist
+        iPluginUid = p->Uid();
+        iInitVolume = ETrue;
+        p->PropertyL( EPbPropertyVolume );
+        iClientList->SendMsgL(
+            TMPXPlaybackMessage(TMPXPlaybackMessage::EPlayerChanged));
+        }
+    // Stop and close opened file
+    TRAP_IGNORE(DoStopL(EFalse));
+    TRAP_IGNORE(p->CommandL(EPbCmdClose));
+
+    // If playing from a playlist, send the index as a data
+    // parameter.  This helps performance as the client
+    // doesn't need to request the index separately
+    TInt index( KErrNotFound );
+    if ( EPlayFromCollection == iPlaySource )
+        {
+        index = iPlaylist->Index();
+        }
+    
+    TMPXPlaybackMessage msg( TMPXPlaybackMessage::EStateChanged,
+                             EPbStateInitialising,
+                             index );
+    SetStateL( msg );
+    iProperties[EPbPropertyPosition]=0;
+    
+    // Check if version2 interface is supported.
+    CDesCArray* interfaces = iPluginHandler->SupportedInterfacesL( p->Uid() );
+    TBool version2InterfaceSupported = EFalse;
+    if (interfaces->MdcaCount())
+        {
+        TInt pos(0);            
+        version2InterfaceSupported = !interfaces->FindIsq(KMPXPlaybackPluginVersion2, pos);
+        }
+    delete interfaces;
+        
+    // cast the plugin to use our interface
+    if (version2InterfaceSupported)
+        {
+        CMPXPlaybackPluginVersion2* plugin = NULL;
+        plugin = static_cast<CMPXPlaybackPluginVersion2*>(p);
+        
+        // if cast was successful, then init streaming with access point
+        if (plugin)
+            {
+            if ( iAccessPointSet )
+                {
+                plugin->InitStreaming64L( *aFile, aAccessPoint );
+                }
+            else
+                {
+                plugin->Initialise64L( *aFile );
+                }
+            }
+        else
+            {
+            MPX_DEBUG1("CMPXPlaybackEngine::Init64L(): -- failure to convert to expected interface");                
+            }
+        }
+    else
+        {
+        MPX_DEBUG1("CMPXPlaybackEngine::Init64L(): expected interface not supported");
+        User::Leave( KErrNotFound );
+        }
+    }
+#endif // SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+
+// End of file