mpxplugins/serviceplugins/playbackplugins/progressdownload/src/mpxprogressdownload.cpp
changeset 0 ff3acec5bc43
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpxplugins/serviceplugins/playbackplugins/progressdownload/src/mpxprogressdownload.cpp	Thu Dec 17 08:45:05 2009 +0200
@@ -0,0 +1,1316 @@
+/*
+* 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:  This class manages progress download
+*
+*/
+
+
+// INCLUDE FILES
+#include <f32plugin.h>
+#include <AudioPreference.h>
+#include <badesca.h>
+#include <apgcli.h>
+#include <mmf/common/mmfcontrollerframeworkbase.h>
+#include <mmf/common/mmfmeta.h>
+#include <mpxcommandgeneraldefs.h>
+#include <mpxmedia.h>
+#include <mpxplaybackpluginobserver.h>
+#include <mpxmediaaudiodefs.h>
+#include <mpxmediamusicdefs.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediadrmdefs.h>
+#include <mpxcmn.h>
+#include <mpxdrmmediautility.h>
+#include <mpxprivatecrkeys.h>
+#include <mpxcenrepwatcher.h>
+#include <mpxlog.h>
+
+#include "mpxprogressdownload.h"
+
+
+// CONSTANTS
+const TUid KProgressDownloadUid={0x101FFC09};
+const TInt KProgressPlayEndThreshold=8000000; // 8 seconds, in milliseconds
+
+_LIT(KMMFMetaEntryAuthor, "author"); // For WMA progressive download
+
+// ============================ LOCAL FUNCTIONS ==============================
+LOCAL_C TInt Balance(TInt aMMFBalance)
+    {
+    return (aMMFBalance-KMMFBalanceCenter) *
+           (EPbBalanceMaxRight-EPbBalanceMaxLeft) /
+           (KMMFBalanceMaxRight-KMMFBalanceMaxLeft);
+    }
+
+LOCAL_C TInt MMFBalance(TInt aBalance)
+    {
+    return KMMFBalanceCenter+(KMMFBalanceMaxRight-KMMFBalanceMaxLeft)/
+           (EPbBalanceMaxRight-EPbBalanceMaxLeft)*aBalance;
+    }
+
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXProgressDownload* CMPXProgressDownload::NewL(TAny* /*aInitParams*/)
+    {
+    CMPXProgressDownload* p=new(ELeave)CMPXProgressDownload();
+    CleanupStack::PushL(p);
+    p->ConstructL();
+    CleanupStack::Pop(p);
+    return p;
+    }
+
+// ----------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::ConstructL()
+    {
+    iVolumeWatcher = CMPXCenRepWatcher::NewL(KCRUidMPXSettings,
+                                             KMPXPlaybackVolume,
+                                             this);
+    iMuteWatcher = CMPXCenRepWatcher::NewL(KCRUidMPXSettings,
+                                           KMPXPlaybackMute,
+                                           this);
+    iFeatureFlag = EPbFeatureBalance | EPbFeatureVolumeRamp;
+    iDrmMediaUtility = CMPXDrmMediaUtility::NewL();
+    }
+
+// ----------------------------------------------------------------------------
+// C++ constructor
+// ----------------------------------------------------------------------------
+//
+CMPXProgressDownload::CMPXProgressDownload()
+    {}
+
+// ----------------------------------------------------------------------------
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CMPXProgressDownload::~CMPXProgressDownload()
+    {
+    delete iMuteWatcher;
+    delete iVolumeWatcher;
+    if ( iDrmMediaUtility )
+        {
+        if ( EPbDlStateDownloadCompleted == iDownloadState )
+            {
+            TRAP_IGNORE( ConsumeRightsL( ContentAccess::EStop ) );
+            }
+        delete iDrmMediaUtility;
+        }
+    if (iPdPlayer)
+        {
+        iPdPlayer->Close();
+        iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPActive,EFalse,KErrNone);
+        delete iPdPlayer;
+        }
+    delete iPdUtil;
+    delete iPdPath;
+    }
+
+// ----------------------------------------------------------------------------
+// Initializes a song for playback
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::InitialiseL(const TDesC& aSong)
+    {
+    MPX_DEBUG2("CMPXProgressDownload::InitialiseL(%S) entering", &aSong );
+
+    // Re-initialize ProgressiveDownloadUtility to make sure multiple sequential
+    // downloads work
+    delete iPdPlayer;
+    iPdPlayer = NULL;
+    delete iPdUtil;
+    iPdUtil = NULL;
+    iPdUtil = CProgressiveDownloadUtility::NewL();
+
+    iPdPlayer = iPdUtil->OpenL( aSong, *this );
+    delete iPdPath;
+    iPdPath = NULL;
+    iPdPath = aSong.AllocL();
+    iDownloadState = EPbDlStateBuffering;
+    iState = EStateInitialising;
+    iConsumeStarted = EFalse;
+
+    MPX_DEBUG1("CMPXProgressDownload::InitialiseL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Initializes a song for playback
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::InitialiseL(RFile& aSong)
+    {
+    MPX_DEBUG1("CMPXProgressDownload::InitialiseL(RFile) entering");
+
+    // Re-initialize ProgressiveDownloadUtility to make sure multiple sequential
+    // downloads work
+    delete iPdPlayer;
+    iPdPlayer = NULL;
+    delete iPdUtil;
+    iPdUtil = NULL;
+    iPdUtil = CProgressiveDownloadUtility::NewL();
+
+    iPdPlayer = iPdUtil->OpenL( aSong, *this );
+    delete iPdPath;
+    iPdPath = NULL;
+    TFileName filename;
+    aSong.FullName(filename);
+    iPdPath = filename.AllocL();
+    iDownloadState = EPbDlStateBuffering;
+    iState = EStateInitialising;
+    iConsumeStarted = EFalse;
+
+    MPX_DEBUG1("CMPXProgressDownload::InitialiseL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a command on the selected song
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::CommandL(TMPXPlaybackCommand aCmd, TInt /*aData*/)
+    {
+    MPX_DEBUG2("CMPXProgressDownload::CommandL(%d) entering", aCmd);
+
+    if (iPdPlayer)
+        {
+        switch(aCmd)
+            {
+            case EPbCmdPlay:
+                {
+                if ( EPbDlStateDownloadCompleted == iDownloadState )
+                    {
+                    if (iConsumeStarted)
+                        {
+                        ConsumeRightsL( ContentAccess::EContinue );
+                        }
+                    else
+                        {
+                        MPX_TRAPD( AEErr,  ConsumeRightsL( ContentAccess::EPlay ) );
+                        if (AEErr == KErrDiskFull)
+                        	{
+                			iDrmMediaUtility->Close();
+                			iPdPlayer->Close();
+                			iState = EStateNotInitialised;
+                			iDownloadState = EPbDlStateNotDownloading;
+                			iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPClosed,
+                                         0, KErrDiskFull);
+				            break;
+                        	}
+                        iConsumeStarted = ETrue;
+                        }
+                    }
+                iPdPlayer->Play();
+                iState = EStateInitialised;
+                iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPPlaying,
+                                         0, KErrNone);
+                break;
+                }
+            case EPbCmdPause:
+                if ( EPbDlStateDownloadCompleted == iDownloadState && iConsumeStarted )
+                    {
+                    ConsumeRightsL( ContentAccess::EPause );
+                    }
+                iPdPlayer->Pause();
+                iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPPaused,
+                                         0, KErrNone);
+                break;
+            case EPbCmdStop:
+                if ( EPbDlStateDownloadCompleted == iDownloadState && iConsumeStarted )
+                    {
+                    ConsumeRightsL( ContentAccess::EStop );
+                    iConsumeStarted = EFalse;
+                    }
+                iDrmMediaUtility->Close();
+                iPdPlayer->Stop();
+                iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPStopped,
+                                         0, KErrNone);
+                break;
+            case EPbCmdClose:
+                if ( EPbDlStateDownloadCompleted == iDownloadState && iConsumeStarted )
+                    {
+                    ConsumeRightsL( ContentAccess::EStop );
+                    iConsumeStarted = EFalse;
+                    }
+                iDrmMediaUtility->Close();
+                iPdPlayer->Close();
+                iState = EStateNotInitialised;
+                iDownloadState = EPbDlStateNotDownloading;
+                iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPClosed,
+                                         0, KErrNone);
+                break;
+            }
+        }
+
+    MPX_DEBUG1("CMPXProgressDownload::CommandL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Executes a command
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::CommandL( CMPXCommand& aCmd )
+    {
+    MPX_FUNC("CMPXProgressDownload::CommandL(CMPXCommand)");
+
+    ASSERT( aCmd.IsSupported( KMPXCommandGeneralId ));
+    TInt id( aCmd.ValueTObjectL<TInt>( KMPXCommandGeneralId ));
+    if ( KMPXCommandIdPlaybackPD == id )
+        {
+        ASSERT(aCmd.IsSupported(KMPXCommandPlaybackGeneralType));
+        TMPXPlaybackPdCommand cmd(
+            static_cast<TMPXPlaybackPdCommand>(
+                aCmd.ValueTObjectL<TInt>(KMPXCommandPlaybackGeneralType)));
+        switch ( cmd )
+            {
+            case ( EPbCmdStartPd ):
+                {
+                ASSERT( aCmd.IsSupported( KMPXCommandPlaybackPDTransactionID ));
+                iTransactionId = aCmd.ValueTObjectL<TUint>( KMPXCommandPlaybackPDTransactionID );
+                break;
+                }
+            case ( EPbCmdFinishPd ):
+                {
+                iObs->HandlePluginEvent(
+                        MMPXPlaybackPluginObserver::EPPlayComplete,
+                        0,
+                        KErrNone);
+                break;
+                }
+            case ( EPbCmdHandlePdEvent ):
+                {
+                ASSERT( aCmd.IsSupported( KMPXCommandPlaybackPDTransactionID ) &&
+                        aCmd.IsSupported( KMPXCommandPlaybackPDEvent ) &&
+                        aCmd.IsSupported( KMPXCommandPlaybackGeneralData ));
+                TUint transId( aCmd.ValueTObjectL<TUint>( KMPXCommandPlaybackPDTransactionID ));
+                TBrCtlDownloadEvent event(
+                    aCmd.ValueTObjectL<TBrCtlDownloadEvent>( KMPXCommandPlaybackPDEvent ));
+                TUint val( aCmd.ValueTObjectL<TUint>( KMPXCommandPlaybackGeneralData ));
+                HandleDownloadEventL( transId, event, val );
+                break;
+                }
+            case ( EPbCmdGetPdStatus ):
+                {
+                aCmd.SetTObjectValueL<TUint>(
+                        KMPXCommandPlaybackPDTransactionID,
+                        iTransactionId );
+                aCmd.SetTObjectValueL<TMPXPlaybackPdDownloadState>(
+                        KMPXCommandPlaybackPDState,
+                        static_cast<TMPXPlaybackPdDownloadState>(iDownloadState));
+                aCmd.SetTObjectValueL<TInt>(
+                        KMPXCommandPlaybackPDDownloadedBytes,
+                        iDownloadBytes );
+                aCmd.SetTObjectValueL<TInt>(
+                        KMPXCommandPlaybackPDTotalBytes,
+                        iDownloadSize );
+                break;
+                }
+            case ( EPbCmdPausePd ):
+                {
+                iObs->HandlePluginEvent(
+                        MMPXPlaybackPluginObserver::EPDownloadCmdPauseDownload,
+                        iTransactionId,
+                        KErrNone );
+                break;
+                }
+            case ( EPbCmdResumePd ):
+                {
+                iObs->HandlePluginEvent(
+                        MMPXPlaybackPluginObserver::EPDownloadCmdResumeDownload,
+                        iTransactionId,
+                        KErrNone );
+                break;
+                }
+            case ( EPbCmdCancelPd ):
+                {
+                iObs->HandlePluginEvent(
+                        MMPXPlaybackPluginObserver::EPDownloadCmdCancelDownload,
+                        iTransactionId,
+                        KErrNone);
+                break;
+                }
+            default:
+                break;
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// Sets a property of the plugin
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::SetL(TMPXPlaybackProperty aProperty, TInt aValue)
+    {
+    MPX_DEBUG3("CMPXProgressDownload::SetL(%d, %d) entering", aProperty, aValue);
+
+    TBool isSupported=ETrue;
+    switch(aProperty)
+        {
+        case EPbPropertyVolume:
+            {
+            SetVolume( aValue );
+            break;
+            }
+        case EPbPropertyVolumeRamp:
+            iPdPlayer->SetVolumeRamp(TTimeIntervalMicroSeconds(TInt64(aValue)));
+            break;
+        case EPbPropertyMute:
+            SetMute( aValue );
+            break;
+        case EPbPropertyBalance:
+            iPdPlayer->SetBalance(MMFBalance(aValue));
+            break;
+        case EPbPropertyPosition:
+            {
+            TInt64 pos(aValue);
+            pos *= KPbMilliMultiplier;
+            iPdPlayer->SetPosition(pos);
+            }
+            break;
+        default:
+            isSupported=EFalse;
+        }
+
+    if (!isSupported)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPSetComplete,
+                             aProperty, KErrNone);
+
+    MPX_DEBUG1("CMPXProgressDownload::SetL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Gets a property of the plugin (async)
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::PropertyL(TMPXPlaybackProperty aProperty) const
+    {
+    MPX_DEBUG2("CMPXProgressDownload::ValueL(%d) entering", aProperty);
+
+    TBool isSupported=ETrue;
+    TInt value=KErrNotFound;
+    TInt err(KErrNone);
+    switch(aProperty)
+        {
+        case EPbPropertyVolume:
+            {
+            value = iVolumeWatcher->CurrentValueL();
+            break;
+            }
+        case EPbPropertyMaxVolume:
+            value=iPdPlayer->MaxVolume();
+            break;
+        case EPbPropertyMute:
+            value = iMuteWatcher->CurrentValueL();
+            break;
+        case EPbPropertyBalance:
+            err = iPdPlayer->GetBalance(value);
+            value=Balance(value);
+            break;
+        case EPbPropertyDuration:
+            {
+            TTimeIntervalMicroSeconds duration = iPdPlayer->Duration();
+            value = duration.Int64() / KPbMilliMultiplier;
+            }
+            break;
+        case EPbPropertyPosition:
+            {
+            TTimeIntervalMicroSeconds pos;
+            iPdPlayer->GetPosition(pos);
+            value = pos.Int64() / KPbMilliMultiplier;
+            }
+            break;
+        case EPbPropertySupportedFeatures:
+            value = iFeatureFlag;
+            break;
+        default:
+            isSupported=EFalse;
+        }
+    if (!isSupported)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    iObs->HandleProperty(aProperty,value,err);
+
+    MPX_DEBUG1("CMPXProgressDownload::ValueL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Gets a list of sub players, UPnP only
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::SubPlayerNamesL()
+    {
+    iObs->HandleSubPlayerNames(KProgressDownloadUid, NULL, ETrue, KErrNone);
+    }
+
+// ----------------------------------------------------------------------------
+// Select a sub player
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::SelectSubPlayerL(TInt /*aIndex*/)
+    {
+    User::Leave(KErrNotSupported);
+    }
+
+// ----------------------------------------------------------------------------
+// Returns current sub player name
+// ----------------------------------------------------------------------------
+//
+const TDesC& CMPXProgressDownload::SubPlayerName()
+    {
+    return KNullDesC; //No subplayer name for local playback
+    }
+
+// ----------------------------------------------------------------------------
+// Current sub player index
+// ----------------------------------------------------------------------------
+//
+TInt CMPXProgressDownload::SubPlayerIndex() const
+   {
+   return KErrNotFound;
+   }
+
+// ----------------------------------------------------------------------------
+// Gets media properties
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::MediaL(const TArray<TMPXAttribute>& aAttrs)
+    {
+    MPX_DEBUG1("CMPXProgressDownload::MediaL() entering");
+
+    RArray<TInt> suppIds;
+    CleanupClosePushL(suppIds);
+    suppIds.AppendL(KMPXMediaIdMusic);
+    suppIds.AppendL(KMPXMediaIdGeneral);
+    suppIds.AppendL(KMPXMediaIdAudio);
+    CMPXMedia* media=CMPXMedia::NewL(suppIds.Array());
+    CleanupStack::PopAndDestroy(&suppIds);
+    CleanupStack::PushL(media);
+
+    TUint attrG(0); // General attributes
+    TUint attrA(0); // Audio attributes
+    TUint attrM(0); // Music attributes
+    TUint attrD(0); // DRM attributes
+
+    for (TInt i=aAttrs.Count(); --i>=0;)
+        {
+        TMPXAttribute attr(aAttrs[i]);
+        if (attr.ContentId() == KMPXMediaIdGeneral)
+            {
+            attrG |= attr.AttributeId();
+            }
+        else if (attr.ContentId() == KMPXMediaIdMusic)
+            {
+            attrM |= attr.AttributeId();
+            }
+        else if (attr.ContentId() == KMPXMediaIdAudio)
+            {
+            attrA |= attr.AttributeId();
+            }
+        else if ( attr.ContentId() == KMPXMediaIdDrm )
+            {
+            attrD |= attr.AttributeId();
+            }
+        }
+
+    // Get number of metadata
+    TInt metaCount = 0;
+
+    // Get metadata from MMF
+    TInt error = iPdPlayer->GetNumberOfMetaDataEntries(metaCount);
+    MPX_DEBUG3("CMPXProgressDownload::MediaL(): metaCount = %d, error = %d", metaCount, error);
+    CMMFMetaDataEntry* metaData = NULL;
+
+    if (!error)
+        {
+        if ( metaCount > 0 )
+            {
+            for (TInt i = 0; i < metaCount; ++i)
+                {
+                metaData = iPdPlayer->GetMetaDataEntryL(i);
+                CleanupStack::PushL(metaData);
+
+                if (metaData->Name().CompareF(KMMFMetaEntrySongTitle()) == 0 &&
+                    attrG & EMPXMediaGeneralTitle)
+                    { // TODO to check request
+                    if ( metaData->Value().Length() > 0 )
+                        {
+                        media->SetTextValueL(
+                            TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                            metaData->Value());
+                        }
+                    else if ( iPdPath )
+                        {
+                        TParsePtrC ptr( *iPdPath );
+                        media->SetTextValueL(
+                            TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                            ptr.Name() );
+                        }
+                    else
+                        {
+                        media->SetTextValueL(
+                            TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                            KNullDesC );
+                        }
+                    }
+                else if( ( metaData->Name().CompareF( KMMFMetaEntryArtist() ) == 0 ||
+                        metaData->Name().CompareF( KMMFMetaEntryAuthor() ) == 0 ) &&
+                    attrM & EMPXMediaMusicArtist)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicArtist),
+                        metaData->Value());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryAlbum()) == 0 &&
+                    attrM & EMPXMediaMusicAlbum)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicAlbum),
+                        metaData->Value());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryYear()) == 0 &&
+                    attrM & EMPXMediaMusicYear)
+                    {
+                    TInt year;
+                    TLex lex( metaData->Value() );
+                    lex.Val( year );
+
+                    TDateTime dt;
+                    dt.SetYear( year );
+                    TTime time( dt );
+
+                    media->SetTObjectValueL(
+                            TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicYear),
+                            time.Int64());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryComment()) == 0 &&
+                    attrG & EMPXMediaGeneralComment)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralComment),
+                        metaData->Value());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryComposer()) == 0 &&
+                    attrM & EMPXMediaMusicComposer)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicComposer),
+                        metaData->Value());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryAlbumTrack()) == 0 &&
+                    attrM & EMPXMediaMusicAlbumTrack)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicAlbumTrack),
+                        metaData->Value());
+                    }
+                else if (metaData->Name().CompareF(KMMFMetaEntryGenre()) == 0 &&
+                    attrM & EMPXMediaMusicGenre)
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicGenre),
+                        metaData->Value());
+                    }
+                //else if (metaData->Name().CompareF(KMMFMetaEntryWOAF()) == 0 &&
+                //    attrM & EMPXMediaMusicGenre)
+                //    {
+                    //media->SetTextValueL(
+                    //    TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicGenre),
+                    //    metaData->Value());
+                    //}
+                else if (metaData->Name().CompareF(KMMFMetaEntryAPIC()) == 0 &&
+                    attrM & EMPXMediaMusicAlbumArtFileName)
+                    {
+                    // TODO check collection if user defined album art available
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicAlbumArtFileName),
+                        *iPdPath);
+                    }
+                CleanupStack::PopAndDestroy(metaData);
+                metaData = NULL;
+                }
+            }
+        else // metaCount == 0
+            {
+            // no metadata available, use file path for a couple of the attributes
+            if ( attrG & EMPXMediaGeneralTitle )
+                { // TODO to check request
+                MPX_DEBUG2( "CMPXProgressDownload::MediaL() iPdPath = 0x%x", iPdPath );
+                if ( iPdPath )
+                    {
+                    TParsePtrC ptr( *iPdPath );
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                        ptr.Name() );
+                    }
+                else
+                    {
+                    media->SetTextValueL(
+                        TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                        KNullDesC );
+                    }
+                }
+            if ( ( attrM & EMPXMediaMusicAlbumArtFileName ) && iPdPath )
+                {
+                // TODO check collection if user defined album art available
+                media->SetTextValueL(
+                    TMPXAttribute(KMPXMediaIdMusic,EMPXMediaMusicAlbumArtFileName),
+                    *iPdPath);
+                }
+            }
+        }
+    else // if error, then use the file path to display (for the Active Idle case)
+        {
+        if ( attrG & EMPXMediaGeneralTitle )
+            {
+            MPX_DEBUG2( "**** CMPXProgressDownload::MediaL() iPdPath = 0x%x", iPdPath );
+            if ( iPdPath )
+                {
+                TParsePtrC ptr( *iPdPath );
+                media->SetTextValueL(
+                    TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                    ptr.Name() );
+                }
+            else
+                {
+                media->SetTextValueL(
+                    TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralTitle),
+                    KNullDesC );
+                }
+            }
+        }
+
+
+   if (attrG & EMPXMediaGeneralUri)
+        {
+        media->SetTextValueL(
+            TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralUri),
+            *iPdPath);
+        }
+
+    if (attrG & EMPXMediaGeneralDuration)
+        {
+        TTimeIntervalMicroSeconds duration = iPdPlayer->Duration();
+        media->SetTObjectValueL<TInt>(
+               TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralDuration),
+               duration.Int64() / KPbMilliMultiplier);
+        }
+
+    // Set bitrate
+    TPckgBuf<TMMFAudioConfig> data;
+
+    const TMMFMessageDestinationPckg
+        destinationPckg(KUidInterfaceMMFAudioController);
+
+    if (attrA & EMPXMediaAudioBitrate)
+        {
+        error = iPdPlayer->CustomCommandSync(destinationPckg,
+            EMMFAudioControllerGetSourceBitRate, KNullDesC8, KNullDesC8, data);
+        if (!error)
+            {
+            media->SetTObjectValueL<TInt>(
+                   TMPXAttribute(KMPXMediaIdAudio, EMPXMediaAudioBitrate),
+                   data().iSampleRate);
+            }
+        }
+
+    if (attrA & EMPXMediaAudioSamplerate)
+        {
+
+        // Set sampling rate
+        error = iPdPlayer->CustomCommandSync(destinationPckg,
+            EMMFAudioControllerGetSourceSampleRate, KNullDesC8, KNullDesC8, data);
+        if (!error)
+            {
+            media->SetTObjectValueL<TInt>(
+                   KMPXMediaAudioSamplerate,
+                   data().iSampleRate);
+            }
+        }
+
+   if (attrG & EMPXMediaGeneralSize)
+        {
+        RFs fs;
+        User::LeaveIfError(fs.Connect());
+        CleanupClosePushL(fs);
+        TEntry entry;
+        fs.Entry(iPdPath->Des(), entry);
+        media->SetTObjectValueL<TInt>(
+               TMPXAttribute(KMPXMediaIdGeneral, EMPXMediaGeneralSize),
+               entry.iSize);
+        CleanupStack::PopAndDestroy(&fs);
+        }
+
+   if (attrG & EMPXMediaGeneralMimeType)
+        {
+        RApaLsSession aps;
+        error  = aps.Connect(); // always fail in console test
+        if (KErrNone == error)
+            {
+            CleanupClosePushL(aps);
+            TDataType dataType;
+            TUid ignore;
+            if(aps.AppForDocument(iPdPath->Des(),ignore,dataType)==KErrNone)
+                {
+                media->SetTextValueL(
+                    TMPXAttribute(KMPXMediaIdGeneral,EMPXMediaGeneralMimeType),
+                    dataType.Des());
+                }
+            CleanupStack::PopAndDestroy(&aps);
+            } // Notes, STIF console test always fail
+        }
+
+    // Set DRM info
+    // Only try to get DRM info if the song has completed downloading
+    MPX_DEBUG2("CMPXProgressDownload::MediaL(): iDownloadState = %d", iDownloadState);
+    if ( EPbDlStateDownloadCompleted == iDownloadState )
+        {
+        const CMPXMedia* drmMedia( iDrmMediaUtility->GetMediaL( attrD ));
+        if ( drmMedia )
+            {
+            TInt count( drmMedia->Count() );
+            for ( TInt i = 0; i < count; i++ )
+                {
+                TUint attrId( drmMedia->Attribute(i).AttributeId() );
+                if ( attrD & attrId )
+                    {
+                    TMPXAttribute mpxAtt( KMPXMediaIdDrm, attrId );
+                    switch ( attrId )
+                        {
+                        case EMPXMediaDrmType:
+                        case EMPXMediaDrmRightsStatus:
+                        case EMPXMediaDrmRightsType:
+                        case EMPXMediaDrmCount:
+                            {
+                            TInt val(
+                                drmMedia->ValueTObjectL<TInt>( mpxAtt ));
+                            media->SetTObjectValueL( mpxAtt, val );
+                            break;
+                            }
+                        case EMPXMediaDrmProtected:
+                        case EMPXMediaDrmSendingAllowed:
+                        case EMPXMediaDrmCanSetAutomated:
+                        case EMPXMediaDrmHasInfoUrl:
+                        case EMPXMediaDrmHasPreviewUrl:
+                        case EMPXMediaDrmAboutToExpire:
+                            {
+                            TBool val(
+                                drmMedia->ValueTObjectL<TBool>( mpxAtt ));
+                            media->SetTObjectValueL( mpxAtt, val );
+                            break;
+                            }
+                        case EMPXMediaDrmStartTime:
+                        case EMPXMediaDrmEndTime:
+                        case EMPXMediaDrmIntervalStartTime:
+                        case EMPXMediaDrmAccumulatedTime:
+                            {
+                            TInt64 val(
+                                drmMedia->ValueTObjectL<TInt64>( mpxAtt ));
+                            media->SetTObjectValueL( mpxAtt, val );
+                            break;
+                            }
+                        case EMPXMediaDrmInterval:
+                            {
+                            TTimeIntervalSeconds val(
+                                drmMedia->ValueTObjectL<TTimeIntervalSeconds>(mpxAtt));
+                            media->SetTObjectValueL( mpxAtt, val );
+                            break;
+                            }
+                        default:
+                            {
+                            break;
+                            }
+                        }   // end switch (attriId)
+                    }   // end if ( attrD & attrId )
+                }
+            }
+        }
+
+    iObs->HandleMedia(*media, KErrNone);
+    CleanupStack::PopAndDestroy(media);
+
+    MPX_DEBUG1("CMPXProgressDownload::MediaL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Cancel request
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::CancelRequest()
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// File open complete event
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::MapcInitComplete(TInt aError,
+                                const TTimeIntervalMicroSeconds& aDuration)
+    {
+    MPX_DEBUG2("CMPXProgressDownload::MapcInitComplete(%d) entering", aError);
+
+    iState = EStateInitialised;
+
+    // Restore volume level
+    if ( KErrNone == aError )
+        {
+        TInt currentVol( 0 );
+        MPX_TRAPD( volError, currentVol = iVolumeWatcher->CurrentValueL() );
+        if ( volError == KErrNone )
+            {
+            SetVolume( currentVol );
+            TBool mute( EFalse);
+            MPX_TRAPD( muteError, mute = iMuteWatcher->CurrentValueL() );
+            if ( muteError == KErrNone && mute )
+                {
+                SetMute(mute);
+                }
+            }
+        }
+
+    if ( iPdPlayer )
+        {
+        MMMFDRMCustomCommand* drmCustom = iPdPlayer->GetDRMCustomCommand();
+        if ( drmCustom )
+            {
+            drmCustom->DisableAutomaticIntent( ETrue );
+            }
+        }
+    if ( EPbDlStateDownloadCompleted == iDownloadState )
+        {
+        TRAP_IGNORE( iDrmMediaUtility->InitL( *iPdPath ));
+        }
+
+    if ( EPbDlStateBuffering == iDownloadState )
+        {
+        iDownloadState = EPbDlStateDownloading;
+        TRAP_IGNORE(
+            iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                                     iDownloadState, aError));
+        }
+
+    TRAP_IGNORE(
+        iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPActive,
+                                 ETrue,aError);
+        iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPInitialised,
+                                aDuration.Int64()/KPbMilliMultiplier,aError);
+        iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPPaused,
+                                 0,aError));
+
+    MPX_DEBUG1("CMPXProgressDownload::MapcInitComplete() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// File play complete event
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::MapcPlayComplete(TInt aError)
+    {
+    MPX_DEBUG2("CMPXProgressDownload::MapcPlayComplete(%d) entering", aError);
+
+    iState = EStateNotInitialised;
+
+    // START WORKAROUND
+    // Check if error is KErrDied and played to the end, then just
+    // treat that as a normal play complete and overwrite the error
+    // handling here
+    // NOTE: This is only a temporary workaround for S60 3.1.
+    // S60 3.2 will have a proper fix in the PD Utility
+    if ( KErrDied == aError )
+        {
+        MPX_DEBUG2("MPXProgressDownload::MapcPlayComplete(): iDownloadState = %d", iDownloadState);
+        if ( EPbDlStateDownloadCompleted == iDownloadState )
+            {
+            TTimeIntervalMicroSeconds dur( iPdPlayer->Duration() );
+            TTimeIntervalMicroSeconds pos;
+            iPdPlayer->GetPosition(pos);
+            if ( Abs( dur.Int64() - pos.Int64() ) < KProgressPlayEndThreshold &&
+                 dur.Int64() > KProgressPlayEndThreshold )
+                {
+                MPX_DEBUG1("CMPXProgressDownload::MapcPlayComplete(): Resetting error to KErrNone");
+                aError = KErrNone;
+                }
+            }
+        }
+    // END WORKAROUND
+
+    // KErrEof is sometimes returned when play finishes at the end
+    if ( KErrEof == aError )
+        {
+        aError = KErrNone;
+        }
+
+    if ( iConsumeStarted )
+        {
+        if ( KErrNone != aError )
+            {
+            TRAP_IGNORE( ConsumeRightsL( ContentAccess::EPause ) );
+            }
+        else
+            {
+            TRAP_IGNORE( ConsumeRightsL( ContentAccess::EStop ) );
+            }
+        iConsumeStarted = EFalse;
+        }
+
+    // If killed by audio policy, mimic a paused state
+    if ( KErrDied == aError )
+        {
+        iObs->HandlePluginEvent( MMPXPlaybackPluginObserver::EPPaused,
+                                 0,
+                                 aError );
+        }
+    else
+        {
+        iObs->HandlePluginEvent( MMPXPlaybackPluginObserver::EPPlayComplete,
+                                 0,
+                                 aError);
+        }
+
+    MPX_DEBUG1("CMPXProgressDownload::MapcPlayComplete() exiting");
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXProgressDownload::Paused
+// -----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::Paused()
+    {
+    MPX_DEBUG1("CMPXProgressDownload::Paused() entering");
+
+    // This callback will only be called when the PD Utility runs out
+    // of data (i.e. all downloaded content has been played).
+    iObs->HandlePluginEvent( MMPXPlaybackPluginObserver::EPPaused,
+                             0,
+                             KErrUnderflow);
+    MPX_DEBUG1("CMPXProgressDownload::Paused() exiting");
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXProgressDownload::Playing
+// -----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::Playing()
+    {
+    MPX_DEBUG1("CMPXProgressDownload::Playing() entering");
+    iObs->HandlePluginEvent(MMPXPlaybackPluginObserver::EPPlaying,
+                             0,
+                             KErrNone);
+    MPX_DEBUG1("CMPXProgressDownload::Playing() exiting");
+    }
+
+// -----------------------------------------------------------------------------
+// CMPXProgressDownload::HandleDownloadEventL
+// -----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::HandleDownloadEventL(TUint aTransactionID,
+                                                TBrCtlDownloadEvent aEvent,
+                                                TUint aValue)
+    {
+    MPX_DEBUG4("CMPXProgressDownload::HandleDownloadEventL(%d, %d, %d) entering",
+               aTransactionID, aEvent, aValue);
+
+    // Notes. It is API in current music player which is called by MusicShop
+    //
+    if (iPdPlayer)
+        {
+        iPdPlayer->HandleDownloadEventL( aTransactionID, aEvent, aValue );
+
+        __ASSERT_DEBUG(
+            aTransactionID == iTransactionId,
+            User::Panic(_L("CMPlayerAudioUIController::HandleProgressiveDownloadEventL"),
+                        KErrArgument));
+
+        switch (aEvent)
+            {
+            case EDownloadEventStarted:
+                {
+                iDownloadState = EPbDlStateBuffering;
+                iDownloadSize = static_cast<TInt>( aValue );
+
+                // send new state
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                            iDownloadState,
+                            KErrNone);
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStarted,
+                            iDownloadSize,
+                            KErrNone );
+                break;
+                }
+            case EDownloadEventCompleted:
+                {
+                iDownloadState = EPbDlStateDownloadCompleted;
+                iDownloadSize = static_cast<TInt>( aValue );
+                iDownloadBytes = iDownloadSize;
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                            iDownloadState,
+                            KErrNone);
+                break;
+                }
+            case EDownloadEventCanceled:
+                {
+                iDownloadState = EPbDlStateNotDownloading;
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                            iDownloadState,
+                            KErrNone);
+                break;
+                }
+            case EDownloadEventError:
+                {
+                iDownloadState = EPbDlStateDownloadError;
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                            iDownloadState,
+                            KErrNone);
+                break;
+                }
+            case EDownloadEventProgress:
+                {
+                if ( EPbDlStateDownloadPaused == iDownloadState )
+                    {
+                    iDownloadState = EPbDlStateDownloading;
+                    iObs->HandlePluginEvent(
+                                MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                                iDownloadState,
+                                KErrNone);
+                    }
+                iDownloadBytes = static_cast<TInt>( aValue );
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadPositionChanged,
+                            iDownloadBytes,
+                            KErrNone);
+                break;
+                }
+            case EDownloadEventPaused:
+                {
+                iDownloadState = EPbDlStateDownloadPaused;
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPDownloadStateChanged,
+                            iDownloadState,
+                            KErrNone);
+                break;
+                }
+            case EDownloadEventPausable:
+                {
+                iFeatureFlag |= EPbFeaturePdPausable;
+                iObs->HandlePluginEvent(
+                            MMPXPlaybackPluginObserver::EPSupportedFeaturesChanged,
+                            iFeatureFlag,
+                            KErrNone);
+                break;
+                }
+            default:
+                {
+                // pass
+                break;
+                }
+            }
+        }
+    MPX_DEBUG1("CMPXProgressDownload::HandleDownloadEventL() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Handle a change in a setting value.
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::HandleSettingChange(
+    const TUid& aRepositoryUid,
+    TUint32 aSettingId )
+    {
+    MPX_DEBUG1("CMPXProgressDownload::HandleSettingChange() entering");
+
+    if ( KCRUidMPXSettings == aRepositoryUid &&
+         KMPXPlaybackVolume == aSettingId )
+        {
+        MPX_DEBUG1("CMPXProgressDownload::HandleSettingChange() Volume setting changed");
+        TInt currentVol( 0 );
+        MPX_TRAPD( volError, currentVol = iVolumeWatcher->CurrentValueL() );
+        if ( KErrNone == volError )
+            {
+            SetVolume( currentVol );
+            }
+        }
+    else if ( KCRUidMPXSettings == aRepositoryUid &&
+         KMPXPlaybackMute == aSettingId )
+        {
+        MPX_DEBUG1("CMPXProgressDownload::HandleSettingChange() Mute setting changed");
+        TBool mute( EFalse );
+        MPX_TRAPD( error, mute = static_cast<TBool>(iMuteWatcher->CurrentValueL()) );
+        if ( error == KErrNone )
+            {
+            TInt oldVolume( 0 );
+            iPdPlayer->GetVolume( oldVolume );
+            if ( (mute && oldVolume != 0) || (!mute && oldVolume == 0) )
+                {
+                SetMute( mute );
+                }
+            }
+        }
+    MPX_DEBUG1("CMPXProgressDownload::HandleSettingChange() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Sets the volume level in audio controller
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::SetVolume( TInt aVolume )
+    {
+    MPX_DEBUG2("CMPXProgressDownload::SetVolume(%d) entering", aVolume);
+
+    // Ensure that level is within min and max values
+    if ( aVolume > KPbPlaybackVolumeLevelMax )
+        {
+        aVolume = KPbPlaybackVolumeLevelMax;
+        }
+    if ( aVolume < KPbPlaybackVolumeLevelMin )
+        {
+        aVolume = KPbPlaybackVolumeLevelMin;
+        }
+
+    TBool changed( EFalse );
+    // Change MMF Audio player's volume
+    if ( EStateInitialised == iState )
+        {
+        TInt newVolume( aVolume * iPdPlayer->MaxVolume() / 100 );
+        MPX_DEBUG2("CMPXProgressDownload::SetVolume(): Setting volume = %d", newVolume);
+
+        // First check if MMF Audio player's volume is changed by new value
+        TInt oldVolume( 0 );
+        iPdPlayer->GetVolume( oldVolume );
+        if ( newVolume != oldVolume )
+            {
+            iPdPlayer->SetVolume( newVolume );
+            changed = ETrue;
+            }
+        }
+
+    // Change setting in cenrep
+    TInt currentVol( 0 );
+    MPX_TRAPD( volError, currentVol = iVolumeWatcher->CurrentValueL() );
+    if ( volError == KErrNone && aVolume != currentVol )
+        {
+        MPX_TRAP( volError, iVolumeWatcher->SetValueL( aVolume ) );
+        }
+
+    // Notify observer if value changed
+    if ( changed )
+        {
+        iObs->HandlePluginEvent( MMPXPlaybackPluginObserver::EPVolumeChanged,
+                                 aVolume,
+                                 KErrNone);
+        }
+
+    MPX_DEBUG1("CMPXProgressDownload::SetVolume() exiting");
+    }
+
+// ----------------------------------------------------------------------------
+// Sets the volume level in audio controller
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::SetMute( TBool aMute )
+    {
+    MPX_DEBUG3("-->CMPXProgressDownload::SetMute 0x%08x vol (%d)", this, aMute);
+
+    TBool changed( EFalse );
+    // Change MMF Audio player's volume
+    TInt currentVolume(0);
+    iPdPlayer->GetVolume(currentVolume);
+    if ( aMute && currentVolume != 0 )
+        {
+        iVolume = currentVolume;
+        iPdPlayer->SetVolume(0);
+        changed = ETrue;
+        }
+    else if ( !aMute && currentVolume == 0 )      // UnMute
+        {
+        iPdPlayer->SetVolume(iVolume);
+        changed = ETrue;
+        }
+
+    // Change setting in cenrep
+    TBool currentMute( EFalse );
+    MPX_TRAPD( muteError, currentMute = iMuteWatcher->CurrentValueL() );
+    if ( muteError == KErrNone )
+        {
+        if ( aMute && !currentMute )
+            {
+            MPX_TRAP( muteError, iMuteWatcher->SetValueL( aMute ) );
+            }
+        else if ( !aMute && currentMute )
+            {
+            MPX_TRAP( muteError, iMuteWatcher->SetValueL( aMute ) );
+            }
+        }
+
+    // Notify observer if value changed
+    if ( changed )
+        {
+        iObs->HandlePluginEvent( MMPXPlaybackPluginObserver::EPMuteChanged,
+                                 aMute,
+                                 KErrNone);
+        }
+
+    MPX_DEBUG3("<--CMPXProgressDownload::SetMute 0x%08x vol (%d)", this, aMute);
+    }
+
+// ----------------------------------------------------------------------------
+// Consumes the rights for the current media
+// ----------------------------------------------------------------------------
+//
+void CMPXProgressDownload::ConsumeRightsL(ContentAccess::TIntent aIntent)
+    {
+    MPX_DEBUG2("-->CMPXProgressDownload::ConsumeRightsL(%d)", aIntent);
+    if ( iPdPlayer )
+        {
+        MMMFDRMCustomCommand* drmCustom = iPdPlayer->GetDRMCustomCommand();
+        if ( drmCustom )
+            {
+            switch ( aIntent )
+                {
+                case ContentAccess::EPlay:
+                case ContentAccess::EStop:
+                case ContentAccess::EPause:
+                case ContentAccess::EContinue:
+                    {
+                    break;
+                    }
+                default:
+                    {
+                    aIntent = ContentAccess::EUnknown;
+                    iConsumeStarted = EFalse;
+                    break;
+                    }
+                }
+            MPX_DEBUG2("-->CMPXProgressDownload::ConsumeRightsL(): Executing intent %d", aIntent);
+            TInt returnCode( drmCustom->ExecuteIntent(aIntent) );
+            MPX_DEBUG2("CMPXProgressDownload::ConsumeRightsL() ExecuteIntent return (%d)", returnCode);
+            User::LeaveIfError(returnCode);
+            }
+        }
+    MPX_DEBUG2("<--CMPXProgressDownload::ConsumeRightsL(%d)", aIntent);
+    }
+
+// End of file